UVa 10603 - Fill

Problem

There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integers not greater than 200). The first and the second jug are initially empty, while the third

is completely filled with water. It is allowed to pour water from one jug into another until either the first one is empty or the second one is full. This operation can be performed zero, one or more times.

You are to write a program that computes the least total amount of water that needs to be poured; so that at least one of the jugs contains exactly d liters of water (d is a positive integer not greater than 200). If it is not possible to measure d liters this way your program should find a smaller amount of water d’ < d which is closest to d and for which d’ liters could be produced. When d’ is found, your program should compute the least total amount of poured water needed to produce d’ liters in at least one of the jugs.

Input

The first line of input contains the number of test cases. In the next T lines, T test cases follow. Each test case is given in one line of input containing four space separated integers - a, b, c and d.

Output

The output consists of two integers separated by a single space. The first integer equals the least total amount (the sum of all waters you pour from one jug to another) of poured water. The second integer equals d, if d liters of water could be produced by such transformations, or equals the closest smaller value d’ that your program has found.

Sample Input

1
2
3
2
2 3 4 2
96 97 199 62

Sample Output

1
2
2 2
9859 62

Solution

題目描述:

有三個桶子,它們各能裝 a , b , 和 c 公升。(a , b , c 都為正整數而且不超過200。)第一,第二個桶子最剛開始是空的,但是第三個桶子卻是裝滿水的。你可以從 X 桶子把水倒入 Y 桶子裡並且把 Y 桶子裝滿,要不然就是把 X 桶子倒乾。倒水的步驟可以執行很多次。

你要寫一個程式去計算整個過程中至少要倒多少水才能達成目標,即這三個桶子中有一個桶子剩 d 公升的水。(d 為正整數而且不超過200。)但是如果你沒有辦法達成目標,也就是沒有辦法讓任何一個桶子剩下 d 公升的水,那麼請達成 d’ 公升,d’ 比 d小但是最接近 d。當 d’ 找到了,請你輸出整個過程至少要倒多少水才能達成 d’ 公升。

題目解法:

這題重新測試,導致之前寫的 DFS 方式直接 TLE 炸掉,只要改寫成 BFS 即可通關。
原理仍一樣,模擬六種互倒入的方式,每一種倒入又牽扯到溢滿的問題。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include <queue>
using namespace std;
#define min(x, y) ((x) < (y) ? (x) : (y))
#define oo 0xfffffff
int A, B, C, D, JUG[3];
int dp[201][201][201], res[201];
queue<int> QA, QB, QC, QTOT;
void pushNode(int a, int b, int c, int tot) {
QA.push(a), QB.push(b), QC.push(c), QTOT.push(tot);
}
void update(int a, int b, int c, int tot) {
if(tot >= res[D]) return;
if(tot >= dp[a][b][c]) return;
dp[a][b][c] = tot;
res[a] = min(res[a], tot);
res[b] = min(res[b], tot);
res[c] = min(res[c], tot);
if(a < B-b) pushNode(0, b+a, c, tot+a);
else pushNode(a-(B-b), B, c, tot+(B-b));
if(a < C-c) pushNode(0, b, c+a, tot+a);
else pushNode(a-(C-c), b, C, tot+(C-c));
if(b < A-a) pushNode(a+b, 0, c, tot+b);
else pushNode(A, b-(A-a), c, tot+(A-a));
if(b < C-c) pushNode(a, 0, c+b, tot+b);
else pushNode(a, b-(C-c), C, tot+(C-c));
if(c < A-a) pushNode(a+c, b, 0, tot+c);
else pushNode(A, b, c-(A-a), tot+(A-a));
if(c < B-b) pushNode(a, b+c, 0, tot+c);
else pushNode(a, B, c-(B-b), tot+(B-b));
}
void bfs(int a, int b, int c, int tot) {
QA.push(a), QB.push(b), QC.push(c), QTOT.push(tot);
while (!QA.empty()) {
a = QA.front(), QA.pop();
b = QB.front(), QB.pop();
c = QC.front(), QC.pop();
tot = QTOT.front(), QTOT.pop();
update(a, b, c, tot);
}
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
int i, j, k;
scanf("%d %d %d %d", &A, &B, &C, &D);
for(i = 0; i <= A; i++)
for(j = 0; j <= B; j++)
for(k = 0; k <= C; k++)
dp[i][j][k] = oo;
JUG[0] = A, JUG[1] = B, JUG[2] = C;
for(i = 0; i <= D; i++)
res[i] = oo;
bfs(0, 0, C, 0);
while(res[D] == oo) D--;
printf("%d %d\n", res[D], D);
}
return 0;
}
Read More +

UVa 12670 - Counting ones

Problem

Carl is right now the happiest child in the world: he has just learned this morning what the binary system is. He learned, for instance, that the binary representation of a positive integer k is a string a[n], a[n-1], …, a[0] where each a[i] is a binary digit 0 or 1, starting with a[n] = 1, and such that k = \sum{i = 0, n} a[i] * 2^ i. It is really nice to see him turning decimal numbers into binary numbers, and then adding and even multiplying them.

Caesar is Carl’s older brother, and he just can’t stand to see his little brother so happy. So he has prepared a challenge: \Look Carl, I have an easy question for you: I will give you two integers A and B, and you have to tell me how many 1’s there are in the binary representation of all the integers from A to B, inclusive. Get ready”. Carl agreed to the challenge. After a few minutes, he came back with a list of the binary representation of all the integers from 1 to 100. \Caesar, I’m ready”. Caesar smiled and said: \Well, let me see, I choose A = 10^15 and B = 10^16. Your list will not be useful”.

Carl hates loosing to his brother so he needs a better solution fast. Can you help him ?

Input

The input file contains several test cases, each of them as described below.
A single line that contains two integers A and B (1 <= A <= B <= 10^16).

Output

For each test case, output a line with an integer representing the total number of digits 1 in the binary representation of all the integers from A to B, inclusive.

Sample Input

1
2
3
1000000000000000 10000000000000000
2 12
9007199254740992 9007199254740992

Sample Output

1
2
3
239502115812196372
21
1

Solution

題目描述:
計算 A 到 B 之間的二進制數出現了幾次 1。

題目解法:
將問題轉換成計算 0 到 A 出現了幾次 1,接著討論在相同長度下 1 出現的次數,之後再遞歸求解。

討論的時候,考慮長度為 n 時,每一位的填法,計算要看切割位置的前半和後半數字,詳細查閱代碼。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
long long mpow(int n, int m) {
long long ret = 1;
for(int i = 1; i <= m; i++)
ret *= n;
return ret;
}
void ito2(long long n, char buf[]) {
if(n == 0) {
buf[0] = '0';
buf[1] = '\0';
return;
}
int i, j, f;
for(i = 63, j = f = 0; i >= 0; i--) {
if((n>>i)&1) f = 1;
if(f) {
buf[j++] = ((n>>i)&1) + '0';
}
}
buf[j] = '\0';
}
void a2toi(long long &r, char buf[]) {
r = 0;
for(int i = 0; buf[i]; i++)
r = r<<1 | (buf[i] - '0');
}
void calc(long long n, long long cnt[]) {
if(n <= 0)
return;
//printf("%d\n", n);
char buf[105];
ito2(n, buf);
int len = strlen(buf);
long long prev = 0;
long long suffix;
calc(mpow(2, len-1)-1, cnt);
//for(int i = 0; i < 10; i++)
// cnt[i] = 0;
long long prev10 = 1;
for(int i = 0; i < len; i++) {
int d = buf[i] - '0';
a2toi(suffix, buf + i + 1);
if(i != len-1)
cnt[d] += suffix + 1;
else
cnt[d]++;
if(i != 0)
cnt[d] += (prev - prev10/2) * mpow(2, len-i-1);
for(int j = i == 0; j < 2; j++) {
if(j == d) continue;
if(j < d) {
if(prev > 0) {
cnt[j] += (prev - prev10/2 + 1) * mpow(2, len-i-1);
} else {
cnt[j] += mpow(2, len-i-1);
}
} else {
if(prev > 0 && prev - prev10/2 > 0) {
cnt[j] += (prev - prev10/2) * mpow(2, len-i-1);
}
}
}
prev10 *= 2;
prev = prev * 2 + d;
}
}
int main() {
long long A, B;
while(scanf("%lld %lld", &A, &B) == 2) {
long long cntA[2] = {}, cntB[2] = {};
calc(A - 1, cntA);
calc(B, cntB);
printf("%lld\n", cntB[1] - cntA[1]);
}
return 0;
}
Read More +

UVa 1449 - Dominating Patterns

Problem

The archaeologists are going to decipher a very mysterious ``language”. Now, they know many language patterns; each pattern can be treated as a string on English letters (only lower case). As a sub string, these patterns may appear more than one times in a large text string (also only lower case English letters).

What matters most is that which patterns are the dominating patterns. Dominating pattern is the pattern whose appearing times is not less than other patterns.

It is your job to find the dominating pattern(s) and their appearing times.

Input

The entire input contains multi cases. The first line of each case is an integer, which is the number of patterns N, 1$\le$N$\le$150. Each of the following N lines contains one pattern, whose length is in range [1, 70]. The rest of the case is one line contains a large string as the text to lookup, whose length is up to 106.

At the end of the input file, number `0’ indicates the end of input file.

Output

For each of the input cases, output the appearing times of the dominating pattern(s). If there are more than one dominating pattern, output them in separate lines; and keep their input order to the output.

Sample Input

1
2
3
4
5
6
7
8
9
10
11
12
13
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0

Sample Output

1
2
3
4
5
4
aba
2
alpha
haha

Solution

題目描述:

給 N 個字串,問在 S 字串中哪些字串出現最多次。

題目解法:

對 N 個字串建造 AC 自動機,將 S 丟入自動機去計算給一個單詞出現次數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
#include <map>
#define maxKind 26
using namespace std;
struct Node{
Node *fail;
Node *next[maxKind];
int cnt;
int who;
Node() {
fail = NULL;
cnt = 0;
who = 0;
memset(next, 0, sizeof(next));
}
};
void build_Trie(const char* str, Node *root, int who) {
Node *p = root;
int i = 0, idx;
while(str[i]) {
if(str[i] >= 'a' && str[i] <= 'z')
idx = str[i] - 'a';
if(p->next[idx] == NULL) {
p->next[idx] = new Node();
}
p = p->next[idx];
i++;
}
p->cnt++;
p->who = who;
}
void build_AC_automation(Node *root) {
root->fail = NULL;
queue<Node*> Q;
Q.push(root);
Node *tn, *p;
while(!Q.empty()) {
tn = Q.front();
Q.pop();
for(int i = 0; i < maxKind; i++) {
if(tn->next[i] == NULL)
continue;
Q.push(tn->next[i]);
p = tn->fail;
while(p != NULL && p->next[i] == NULL)
p = p->fail;
if(p == NULL)
tn->next[i]->fail = root;
else
tn->next[i]->fail = p->next[i];
}
}
}
void free_AC_automation(Node *root) {
queue<Node*> Q;
Q.push(root);
Node *tn, *p;
while(!Q.empty()) {
tn = Q.front();
Q.pop();
for(int i = 0; i < maxKind; i++) {
if(tn->next[i] != NULL) {
Q.push(tn->next[i]);
}
}
free(tn);
}
}
void query(const char* str, Node *root, int cnt[]) {
int i = 0, idx;
Node *tn, *p;
tn = root;
while(str[i]) {
if(str[i] >= 'a' && str[i] <= 'z')
idx = str[i] - 'a';
while(tn->next[idx] == NULL && tn != root)
tn = tn->fail;
tn = tn->next[idx];
tn = (tn == NULL) ? root : tn;
p = tn;
while(p != root) {
if(p->cnt > 0)
cnt[p->who]++;
p = p->fail;
}
i++;
}
}
char buf[1048576], pattern[256][256];
int main() {
int n;
while(scanf("%d", &n) == 1 && n) {
Node *root = new Node();
for(int i = 0; i < n; i++) {
scanf("%s", pattern[i]);
build_Trie(pattern[i], root, i+1);
}
build_AC_automation(root);
scanf("%s", buf);
int cnt[256] = {};
query(buf, root, cnt);
free_AC_automation(root);
int maxMatch = cnt[0];
for(int i = 0; i < n; i++) {
maxMatch = max(maxMatch, cnt[i+1]);
}
printf("%d\n", maxMatch);
for(int i = 0; i < n; i++) {
if(cnt[i+1] == maxMatch)
printf("%s\n", pattern[i]);
}
}
return 0;
}
Read More +

UVa 1494 - Qin Shi Huang's National Road System

Problem

During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China – they were Qi, Chu, Yan, Han, Zhao, Wei and Qin. Ying Zheng was the king of the kingdom Qin. Through 9 years of wars, he finally conquered all six other kingdoms and became the first emperor of a unified China in 221 BC. That was Qin dynasty – the first imperial dynasty of China(not to be confused with the Qing Dynasty, the last dynasty of China). So Ying Zheng named himself “Qin Shi Huang” because “Shi Huang” means “the first emperor “ in Chinese.

\epsfbox{p5713.eps}

Qin Shi Huang undertook gigantic projects, including the first version of the Great Wall of China, the now famous city-sized mausoleum guarded by a life-sized Terracotta Army, and a massive national road system. There is a story about the road system:

There were n cities in China and Qin Shi Huang wanted them all be connected by n - 1 roads, in order that he could go to every city from the capital city Xianyang. Although Qin Shi Huang was a tyrant, he wanted the total length of all roads to be minimum,so that the road system may not cost too many people’s life. A daoshi (some kind of monk) named Xu Fu told Qin Shi Huang that he could build a road by magic and that magic road would cost no money and no labor. But Xu Fu could only build ONE magic road for Qin Shi Huang. So Qin Shi Huang had to decide where to build the magic road. Qin Shi Huang wanted the total length of all none magic roads to be as small as possible, but Xu Fu wanted the magic road to benefit as many people as possible – So Qin Shi Huang decided that the value of A/B (the ratio of A to B) must be the maximum, which A is the total population of the two cites connected by the magic road, and B is the total length of none magic roads.

Would you help Qin Shi Huang?

A city can be considered as a point, and a road can be considered as a line segment connecting two points.

Input

The first line contains an integer t meaning that there are t test cases (t < 10).

For each test case:

The first line is an integer n meaning that there are n cities (2 < n <= 1000).

Then n lines follow. Each line contains three integers X, Y and P (0 < X, Y <= 1000, 0 < P < 100000). (X, Y) is the coordinate of a city and P is the population of that city.

It is guaranteed that each city has a distinct location.

Output

For each test case, print a line indicating the above mentioned maximum ratio A/B. The result should be rounded to 2 digits after decimal point.

Sample Input

1
2
3
4
5
6
7
8
9
10
2
4
1 1 20
1 2 30
200 2 80
200 1 100
3
1 1 20
1 2 30
2 2 40

Sample Output

1
2
65.00
70.00

Solution

題目描述:

有 n 個城市,在中國秦始皇希望他們都用連接 n - 1 道路,以便他可以去到每一個城市從首都咸陽。儘管秦始皇是個暴君,他希望所有的道路是最低的總長度,從而使道路系統可能不會花費太多勞力。倒是一個(一些和尚)命名徐福告訴秦始皇,他可以通過魔法修路和魔法的道路將花費沒用錢,沒用勞動力。但徐福只能建一個神奇的道路秦始皇。所以,秦始皇不得不決定在哪裡建造魔法的道路。秦始皇想所有無魔法的道路是盡可能小的總長度,但徐福希望魔法道路可以效益為盡可能多的人。所以秦始皇決定 A / B 必須是最大的,其中 A 是魔法路兩端的總人口,而 B 是沒有魔法的道路的總長度。

題目解法:

找出 MST,窮舉所有所有魔法路的可能。

對於一個 MST 修改一條邊,可在 O(n) 時間內找到環,之後將環上最重的邊去除即可。
但是這題中,MST 會保留住,因此對 MST 任兩點路徑上的最重邊進行在 O(n^2) 內完成計算。

  • MST 加入新點,可以在 O(n) 時間內完成 ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <vector>
using namespace std;
struct E {
int x, y, v;
E(int a=0, int b=0, int c=0):
x(a), y(b), v(c) {}
bool operator<(const E &a) const {
return v < a.v;
}
};
E D[1000005];
vector<E> tree[1005];
int p[1005], rank[1005];
int findp(int x) {
return p[x] == x ? x : (p[x] = findp(p[x]));
}
int joint(int x, int y) {
x = findp(x), y = findp(y);
if(x == y)
return 0;
if(rank[x] > rank[y])
rank[x] += rank[y], p[y] = x;
else
rank[y] += rank[x], p[x] = y;
return 1;
}
double kruscal(int n, int m) {
double sum = 0;
sort(D, D+m);
for(int i = 0; i < n; i++) {
p[i] = i, rank[i] = 1;
tree[i].clear();
}
for(int i = 0; i < m; i++) {
if(joint(D[i].x, D[i].y)) {
sum += sqrt(D[i].v);
tree[D[i].x].push_back(E(D[i].x, D[i].y, D[i].v));
tree[D[i].y].push_back(E(D[i].y, D[i].x, D[i].v));
}
}
return sum;
}
int visited[1005];
double maxEdge[1005][1005];
void dfs(int u, int n) {
visited[u] = 1;
for(int i = 0; i < tree[u].size(); i++) {
int v = tree[u][i].y;
if(visited[v]) continue;
double cost = sqrt(tree[u][i].v);
maxEdge[u][v] = maxEdge[v][u] = cost;
for(int j = 0; j < n; j++) {
if(visited[j]) {
maxEdge[j][v] = maxEdge[v][j] = max(maxEdge[j][u], cost);
}
}
dfs(v, n);
}
}
int main() {
int testcase;
scanf("%d", &testcase);
while(testcase--) {
int n, e;
int X[1005], Y[1005], P[1005];
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d %d %d", &X[i], &Y[i], &P[i]);
e = 0;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
D[e++] = E(i, j, (X[i] - X[j])*(X[i] - X[j])
+ (Y[i] - Y[j])*(Y[i] - Y[j]));
}
}
double mstcost = kruscal(n, e);
double ret = 0;
for(int i = 0; i < n; i++)
visited[i] = 0;
dfs(0, n);
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
ret = max(ret, (P[i] + P[j])/(mstcost - maxEdge[i][j]));
}
}
printf("%.2lf\n", ret);
}
return 0;
}
Read More +

UVa 1417 - Traffic Jam

Problem

The kingdom of Tripbansai has an unusual traffic system. The city locations in the kingdom can be described as a grid and all the roads connect neighboring cities. This rectangular grid has 2 rows and C columns where every point represents a city. So there are 2 C cities and 3 C - 2 roads in this system.

Sometimes two adjacent cities become disconnected because of traffic jam, and sometimes the traffic problem has been solved so that a road can be usedd again. We can assume that every road is closed at first.

Ministry of Communications will give some instructions to you. Your task is to implement a program as a traffic response information system.

Each instruction appears as a single line in one ofthe formats below:

Close r1 c1 r2 c2 Close the road connecting the adjacent cities located on (r1, c1) and (r2, c2) .
Open r1 c1 r2 c2 Open the road connecting the adjacent cities located on (r1, c1) and (r2, c2) .
Ask r1 c1 r2 c2 Reply with Y if there exists a way from the city on (r1, c1) to the city on (r2, c2) ;
reply with N if there doesn’t.
Exit No more requests are forthcoming. The problem should exit.

Input

The first line ofthe input contains a single integer T (1$\le$T$\le$11) , representing the number of test cases that follow.

The first line of each test case consists of a single integer C (1$\le$C$\le$100000) , which is the number of columns.

There are some lines following, each for an instruction. Each test case ends with an instruction ``Exit”. There are no more than 100000 instructions in each test case. All the roads are closed initially, and each case is an independent problem.

Output

For each instruction Ask r1 c1 r2 c2, display a line containing Y or N.

Sample Input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
3
2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit
3
Open 1 1 1 2
Ask 1 1 1 2
Close 1 1 1 2
Ask 1 1 1 2
Exit
2
Open 1 1 1 2
Open 1 2 2 2
Open 2 1 2 2
Ask 1 1 2 1
Exit

Sample Output

1
2
3
4
5
Y
N
Y
N
Y

Solution

題目描述:

對於一個 2 x C 的方格點來說,將會有 3 * C - 2 條邊。

題目解法:

維護一個區間角落四個點之間的連接資訊,也就是總共六種。

  • c[0] 左上右上
  • c[1] 左上右下
  • c[2] 左下右上
  • c[3] 左下右下
  • c[4] 左上左下
  • c[5] 右上右下

上方 r = 1 下方 r = 2 左方 c = left 右方 c = right

對於區間 [l, r] 我們只維護這個區間的資訊,不考慮繞此外的結果。
而對於區間的編號,由左而右,構成 0, 1, 2, 3, …, C,每一個可以看作是一個方格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct Node {
int c[6];
}; // - \ / _ | |
Node ST[262144 + 10];
void build(int k, int l, int r) {
if(l > r) return;
if(l == r) {
memset(&ST[k], 0, sizeof(ST[k]));
return;
}
int mid = (l + r)/2;
build(k<<1, l, mid);
build(k<<1|1, mid+1, r);
}
Node combine(Node s1, Node s2) {
Node s;
s.c[0] = (s1.c[0] && s2.c[0]) || (s1.c[1] && s2.c[2]);
s.c[1] = (s1.c[0] && s2.c[1]) || (s1.c[1] && s2.c[3]);
s.c[2] = (s1.c[2] && s2.c[0]) || (s1.c[3] && s2.c[2]);
s.c[3] = (s1.c[2] && s2.c[1]) || (s1.c[3] && s2.c[3]);
s.c[4] = (s1.c[4]) || (s1.c[0] && s2.c[4] && s1.c[3]);
s.c[5] = (s2.c[5]) || (s2.c[0] && s1.c[5] && s2.c[3]);
return s;
}
void modify(int k, int l, int r, int qidx, int qfield, int qval) {
if(l > r) return;
if(l == r) {
ST[k].c[qfield] = qval;
ST[k].c[1] = (ST[k].c[0] && ST[k].c[5]) || (ST[k].c[3] && ST[k].c[4]);
ST[k].c[2] = (ST[k].c[0] && ST[k].c[4]) || (ST[k].c[3] && ST[k].c[5]);
return;
}
int mid = (l + r)/2;
if(qidx > mid)
modify(k<<1|1, mid+1, r, qidx, qfield, qval);
else
modify(k<<1, l, mid, qidx, qfield, qval);
ST[k] = combine(ST[k<<1], ST[k<<1|1]);
}
Node query(int k, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr)
return ST[k];
int mid = (l + r)/2;
if(ql > mid)
return query(k<<1|1, mid+1, r, ql, qr);
else if(qr <= mid)
return query(k<<1, l, mid, ql, qr);
else
return combine(query(k<<1, l, mid, ql, qr),
query(k<<1|1, mid+1, r, ql, qr));
}
int main() {
int testcase, C;
int r1, r2, c1, c2;
int lines = 0;
char cmd[10];
scanf("%d", &testcase);
while(testcase--) {
scanf("%d", &C);
memset(ST, 0, sizeof(ST));
build(1, 0, C);
while(scanf("%s", cmd) == 1 && cmd[0] != 'E') {
scanf("%d %d %d %d", &r1, &c1, &r2, &c2);
if(cmd[0] == 'O' || cmd[0] == 'C') { // open
int qval = cmd[0] == 'O' ? 1 : 0;
if(c1 != c2) {
modify(1, 0, C, min(c1, c2), r1 == 1 ? 0 : 3, qval);
} else {
modify(1, 0, C, min(c1, c2) - 1, 5, qval);
modify(1, 0, C, min(c1, c2), 4, qval);
}
} else {
if(c1 > c2) {
swap(c1, c2);
swap(r1, r2);
}
if(r1 == r2 && c1 == c2) {
puts("Y");
} else if(r1 != r2 && c1 == c2) {
Node l = query(1, 0, C, 0, c1 - 1);
Node r = query(1, 0, C, c1, C);
if(l.c[5] || r.c[4])
puts("Y");
else
puts("N");
} else {
Node l = query(1, 0, C, 0, c1 - 1);
Node r = query(1, 0, C, c2, C);
Node m = query(1, 0, C, c1, c2 - 1);
int kc[2][2] = { {0, 1}, {2, 3} };
if(m.c[kc[r1 - 1][r2 - 1]] ||
(l.c[5] && m.c[kc[(3 - r1) - 1][r2 - 1]]) ||
(r.c[4] && m.c[kc[r1 - 1][(3 - r2) - 1]]) ||
(l.c[5] && r.c[4] && m.c[kc[(3 - r1) - 1][(3 - r2) - 1]]))
puts("Y");
else
puts("N");
}
}
}
}
return 0;
}
Read More +

UVa 1608 - Non-boring sequences

Problem

We were afraid of making this problem statement too boring, so we decided to keep it short. A sequence is called non-boring if its every connected subsequence contains a unique element, i.e. an element such that no other element of that subsequence has the same value.
Given a sequence of integers, decide whether it is non-boring.

Input

The first line of the input contains the number of test cases T. The descriptions of the test cases follow:
Each test case starts with an integer n (1 <= n <= 200000) denoting the length of the sequence. In the next line the n elements of the sequence follow, separated with single spaces. The elements are non-negative integers less than 10^9.

Output

Print the answers to the test cases in the order in which they appear in the input. For each test case print a single line containing the word non-boring or boring.

Sample Input

1
2
3
4
5
6
7
8
9
4
5
1 2 3 4 5
5
1 1 1 1 1
5
1 2 3 2 1
5
1 1 2 1 1

Sample Output

1
2
3
4
non-boring
boring
non-boring
boring

Solution

題目描述:

對於所有連續區間,都符合至少有一個獨特的數字。即每個區間中都會有一個數字不重複。

題目解法:

對於一個區間 [l, r] 來說,符合條件時,會存在一個獨特的數字位於 m,則對於 i in [l, m-1] and j in [m+1, r],所有 [i, j] 產生的區間必然會符合,則遞歸下去查找 [l, m-1][m+1, r] 有沒有符合。

這題有趣的地方在於-如何快速得到這個獨特數字,不過也不難想地,建出數字的前一個相同和下一個相同。判斷該數字在區間是獨特時,則前一個和下一個皆不會在區間中。

這樣仍不會通過測資,如果是想要接近中間的方式去切割,則會接受 TLE 的殘酷事實,當初在想是不是遞迴太深還怎麼的,這裡留下困惑,根據快速排序的經驗,如果切割點在中間是比較好的,複雜度為 O(n log n)

lang: cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <algorithm>
#include <map>
using namespace std;
int A[262144];
int NEXT[262144], PREV[262144];
map<int, int> R;
int dfs(int l, int r) {
if(l >= r) return 1;
for(int i = 0; i <= (r-l+1)/2; i++) {
if(NEXT[l+i] > r && PREV[l+i] < l)
return dfs(l, l+i-1) && dfs(l+i+1, r);
if(NEXT[r-i] > r && PREV[r-i] < l)
return dfs(l, r-i-1) && dfs(r-i+1, r);
}
return 0;
}
int main() {
int testcase, n;
scanf("%d", &testcase);
while(testcase--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &A[i]);
NEXT[i] = n+1;
PREV[i] = 0;
}
R.clear();
for(int i = 1; i <= n; i++) {
PREV[i] = R[A[i]], NEXT[PREV[i]] = i;
R[A[i]] = i;
}
puts(dfs(1, n) ? "non-boring" : "boring");
}
return 0;
}
/*
20
6
1 2 3 1 2 3
5
1 2 3 4 5
5
1 1 1 1 1
5
1 2 3 2 1
5
1 1 2 1 1
*/
Read More +

UVa 12345 - Dynamic len(set(a[L:R]))

Problem

In python, we can use len(start(a[L:R])) to calculate the number of distinct values of elements a[L], a[L+1], …, a[R-1].

Here are some interactive examples that may help you understand how it is done. Remember that the indices of python lists start from 0.

1
2
3
4
5
6
7
8
9
10
11
12
>>> a=[1,2,1,3,2,1,4]
>>> print a[1:6]
[2, 1, 3, 2, 1]
>>> print set(a[1:6])
set([1, 2, 3])
>>> print len(set(a[1:6]))
3
>>> a[3]=2
>>> print len(set(a[1:6]))
2
>>> print len(set(a[3:5]))
1

Your task is to simulate this process.

Input

There will be only one test case. The first line contains two integers n and m (1 ≤ n,m ≤ 50,000). The next line contains the original list.

All the integers are between 1 and 1,000,000 (inclusive). The next m lines contain the statements that you need to execute.

A line formatted as “M x y” (1 ≤ y ≤ 1,000,000) means “a[x] = y”, and a line formatted as “Q x y” means “print len(set(a[x:y]))”.

It is guaranteed that the statements will not cause “index out of range” error.

Output

Print the simulated result, one line for each query.

Sample Input

1
2
3
4
5
6
7 4
1 2 1 3 2 1 4
Q 1 6
M 3 2
Q 1 6
Q 3 5

Output for Sample Input

1
2
3
3
2
1

Solution

題目描述:

  1. 支持查找區間內有多少不同數字。
  2. 支持單點值修改

題目解法:

維護每一個數字的前面相同數字的位置,如果前面沒有一樣的就是 -1

1
2
3
i 0 1 2 3 4 5 6
A[] 1 2 1 3 2 1 4
P[] -1 -1 0 -1 1 2 -1

對於詢問 [l, r],返回 P[l, r] 內小於 l 的個數。

這裡使用塊狀表維護資訊,也可以使用 線段樹 + 平衡樹。

  • 塊狀表 作法

    • 對於詢問
      對於完整的塊進行二分搜尋。如果所在是不完整的塊,則窮舉搜尋。
    • 對於修改

      • 向後搜索舊值
        將指向自己的修改成原本指向的。
      • 向前搜索新值
        將指向連到前方的相同數字。
      • 向後搜索新值
        將後面最靠近的相同數字連向自己。
    • 維護資訊

      • 堆的 prev 排序後的資訊
        用在詢問 query 區間內小於 l 的二分搜
      • 堆的 value 排序後的資訊
        維護 prev 時,查找前一個和後一個的時候使用。
    • 堆更新時,最簡單是直接排序,複雜度 O(sqrt(n) * log(sqrt(n))) 看起來是不會很多,如果不使用這種方式,則必須對 prev 和 value 數組增加映射來找到相對應的原位置,然後用插入排序的方式,達到 O(sqrt(n))。但是在 UVa 運行前者在 1.200 s 左右,基本上可以不用再優化,紀錄的資訊增加一倍 又或者 代碼要長一點。

每一個操作約在 O(sqrt(n)) 時間內完整,塊狀表不用做合併操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <stdio.h>
#include <map>
#include <string.h>
#include <algorithm>
using namespace std;
int pSIZE, pCOUNT;
int Pval[256][256], Ppre[256][256], Plen[256];
int A[65536], P[65536];
void build(int n) {
int pxIdx = -1, pyIdx = pSIZE;
map<int, int> PREV;
map<int, int>::iterator it;
memset(Plen, 0, sizeof(Plen));
for(int i = 0; i < n; i++) {
if(pyIdx == pSIZE)
pxIdx++, pyIdx = 0;
Pval[pxIdx][pyIdx] = A[i];
it = PREV.find(A[i]);
if(it == PREV.end()) {
Ppre[pxIdx][pyIdx] = -1;
PREV[A[i]] = i;
} else {
Ppre[pxIdx][pyIdx] = it->second;
it->second = i;
}
P[i] = Ppre[pxIdx][pyIdx];
pyIdx++;
Plen[pxIdx] = pyIdx;
}
pCOUNT = pxIdx + 1;
for(int i = 0; i < pCOUNT; i++) {
sort(Pval[i], Pval[i] + Plen[i]);
sort(Ppre[i], Ppre[i] + Plen[i]);
}
}
int query(int L, int R) {
int B = L;
int ret = 0;
while(L%pSIZE && L <= R) {
if(P[L] < B) ret++;
L++;
}
while((R+1)%pSIZE && L <= R) {
if(P[R] < B) ret++;
R--;
}
if(L > R) return ret;
L /= pSIZE, R /= pSIZE;
while(L <= R) {
int cnt = upper_bound(Ppre[L], Ppre[L] + pSIZE, B - 1) - Ppre[L];
ret += cnt;
L++;
}
return ret;
}
void updatePrev(int x) {
for(int i = x * pSIZE, j = 0; j < Plen[x]; i++, j++)
Ppre[x][j] = P[i];
sort(Ppre[x], Ppre[x] + Plen[x]);
}
void update(int x) {
for(int i = x * pSIZE, j = 0; j < Plen[x]; i++, j++)
Pval[x][j] = A[i], Ppre[x][j] = P[i];
sort(Pval[x], Pval[x] + Plen[x]);
sort(Ppre[x], Ppre[x] + Plen[x]);
}
void getNext(int x, int val, int &NEXT, int &nx) {
int y = x/pSIZE * pSIZE + Plen[x / pSIZE] - 1;
NEXT = 0x3f3f3f3f, nx = -1;
while(x%pSIZE && x <= y) {
if(A[x] == val) {
NEXT = x, nx = x / pSIZE;
return;
}
x++;
}
int L = x / pSIZE, R = pCOUNT - 1;
if(L * pSIZE < x) return;
for(int i = L; i <= R; i++) {
int pos = binary_search(Pval[i], Pval[i] + Plen[i], val);
if(pos == true) {
NEXT = i * pSIZE;
while(A[NEXT] != val) NEXT++;
nx = i;
return;
}
}
}
void getPrev(int y, int val, int &PREV, int &px) {
int x = 0;
PREV = -1, px = -1;
while((y+1)%pSIZE && x <= y) {
if(A[y] == val) {
PREV = y, px = y / pSIZE;
return;
}
y--;
}
int L = 0, R = y / pSIZE;
if(R * pSIZE > y) return;
for(int i = R; i >= L; i--) {
int pos = binary_search(Pval[i], Pval[i] + Plen[i], val);
if(pos == true) {
PREV = i * pSIZE + Plen[i] - 1;
while(A[PREV] != val) PREV--;
px = i;
return;
}
}
}
void modify(int X, int nval) {
if(A[X] == nval) return ;
int oval = A[X];
int NEXT, PREV, nx, px;
PREV = P[X], px = -1;
if(PREV >= 0) px = PREV / pSIZE;
getNext(X + 1, oval, NEXT, nx);
if(nx != -1) {
P[NEXT] = PREV;
updatePrev(nx);
}
getNext(X + 1, nval, NEXT, nx);
if(nx != -1) {
P[NEXT] = X;
updatePrev(nx);
}
getPrev(X - 1, nval, PREV, px);
A[X] = nval, P[X] = PREV;
update(X / pSIZE);
}
int main() {
// freopen("in.txt", "r+t", stdin);
// freopen("out2.txt", "w+t", stdout);
int n, m, L, R;
char cmd[4];
while(scanf("%d %d", &n, &m) == 2) {
for(pSIZE = 1; pSIZE * pSIZE < n; pSIZE++);
for(int i = 0; i < n; i++)
scanf("%d", &A[i]);
build(n);
while(m--) {
scanf("%s %d %d", cmd, &L, &R);
if(cmd[0] == 'Q') {
R--;
int r = query(L, R);
printf("%d\n", r);
} else {
modify(L, R);
}
}
}
return 0;
}
/*
30 50
4 19 18 17 16 7 16 9 18 14 4 11 4 2 8 8 1 3 1 5 5 8 3 8 11 17 10 0 2 16
M 20 12
Q 2 29
M 8 9
Q 7 7
M 25 12
M 19 13
Q 12 22
Q 8 11
M 5 5
M 15 8
Q 9 26
*/
Read More +

CCPC 2014 中程杯紀錄

在此先感謝 inker 帶我出門!當然也感謝 彰師大 這次辦的程式競賽。這是一場久違的比賽,同時也是這學期最後一場,原因是因為太久沒參賽,導致往後的桂冠賽也無法參加。

至於討厭比賽的問題,這一篇就不多說了。記得下次繼續支持彰師大資工辦的活動,免得像靜宜大學被玩壞了。 CCPC 官網

賽前

比賽前日進發 inker 豪宅,中間歷經坐錯區間車,到比賽會場前,徒步走了三十分鐘到火車站搭車 … 各種經歷深感出門是件難事。跟我肯定是不幸的,應該多少有點關聯。

上次比賽是很久之前的事情,想到這次還會遭遇國手,還有清華交大的選手,深感害怕。在這情況下,要出門見人什麼的,讓我窩回宿舍吧!

題目

Problem A Non-boring sequences

UVa 1608 - Non-boring sequences

結果題目還是讀錯了,對於任意連續區間,都存在一個獨特的數字。

很容易誤解 connected subsequence 簡單的說就是相鄰兩個元素。
這題由於讀題錯誤,在全場第一個送出的同時拿下的 Wrong Answer
在假解的情況下,居然通過了測試。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
#include<stdio.h>
#include<map>
using namespace std;
int t, n, h1,h2;
int main(){
scanf("%d", &t);
while(t --){
scanf("%d", &n);
map<int, bool> mp;
int i = 0;
bool yes = true;
int pre = -1;
for(i = 0 ; i < n ; i ++)
{
scanf("%d", &h2);
if(pre == h2){
yes = false;
}
pre = h2;
}
printf(yes?"non-boring\n":"boring\n");
}
return 0;
}

Problem B Traffic Jam

UVa 1417 - Traffic Jam

這題是全場最噁心的題目,但是沒想到有人用 BFS 還是 DFS 在每個詢問就過了。

賽完看到記分板表示非常火。

猜測解法如下,採用線段樹的方式。

觀察

2014 CCPC B01
2014 CCPC B02

對於任兩點詢問假設這個區間是 [l, r],不管同側還是異測,當然你也可以假設兩旁還有可以連的。發現對於區間 [l, r] 的點來說,會有左上無法到右下的情況或者左下無法到右上,兩者只有符合一個條件就可以說出 NO

推倒

2014 CCPC B03

因此我們維護區間 [l, r] 的左上到右下、左下到右上的連通性。

對於區間 S 來說,可以切成 S1 和 S2,維護四條資訊,連通性有無 0/1。

  • A(左上, 右下) =
    • S1.A & S2.A & (wx || yz)
    • S1.A & S2.D & (z || wxy)
    • S1.C & S2.A & (x || wyz)
    • S1.C & S2.D & (wz || xy)
  • B(左下, 右上)
  • C(左上, 右上)
  • D(左下, 右下)

剩餘 BCD 三條類推,有空的時候再來填滿它,也就是說,之後的開邊跟閉邊都屬於單點更新,因此可以在 O(log n) 時間內完成。對於詢問兩點時,找到 [l, r] 查找 A || B 的結果,由於線段樹會切成數個區間,這個時候要由左而右依序組合即可。

Problem C Finding the Prime Implicants of a Boolean Function

這題就是單純複雜,但是輸入卻不明確。主辦單位有說會忽略空白比對,但是對於 Invaild input format 來說,題目也沒有說清楚輸入格式。

好吧,硬著頭皮做,至少把範例輸入輸出弄了一樣,但是卻砸了。

對了,關於 subset 有個快速地找法。

1
2
3
for(int j = (i-1)&i; j > 0; j--, j &= i) {
// j 是 i 的 subset
}

這個寫法會在幾題的 UVa 中見到,速度快了 X 倍,不過這題測資沒有強成這樣,也許只是我寫太瘋狂了,想不到更好的解法來完成。最後掛了 Wrong Answer,直接默哀數分鐘。在我心中-她過了。

這題就是窮舉,將每一種組合拆成兩個去合併,而每一種組合(16 bits)如果能合併成一個 product item 則用一個 exist(4 bits)mark(4 bits) 表示,

因此,對於每一個組合拆成 a, b,其中 a.exist == b.exist,同時變數差異只會有一個。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include <stdio.h>
#include <map>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <sstream>
#include <set>
using namespace std;
//int A[105] = {0, 2, 3, 5,7 ,8, 9, 10, 11, 13, 15}, n = 11;
//int A[105] = {0, 1, 2, 5, 6, 7, 8, 9, 10, 14}, n = 10;
int A[1024], n;
unsigned int result[1<<16] = {};
unsigned int mergeV[1<<16] = {};
struct cmp {
bool operator()(const int a, const int b) const {
for(int i = 0; i < 16; i++) {
int ia, ib;
ia = (a>>i)&1;
ib = (b>>i)&1;
if(ia != ib)
return ia > ib;
}
return a < b;
}
};
void solv() {
map<unsigned int, int> combine;
map<unsigned int, int> combineN;
for(int i = 0; i < (1<<16); i++) {
result[i] = mergeV[i] = 0;
}
for(int i = 0; i < n; i++) {
unsigned int mark = 15; // exits
unsigned int ssss = A[i];
combine[(ssss<<16)|mark]++;
combineN[(ssss<<16)|mark] = 1<<A[i];
result[1<<A[i]] = (ssss<<16)|mark;
mergeV[1<<A[i]] = 1;
}
for(int i = 1; i < (1<<16); i++) {
if((i&(-i)) == i)
continue;
int ok = 0;
unsigned int V;
for(int j = 1; j < i; j++) {
if((i&j) == j) {
int a, b;
a = j, b = i^j;
if(mergeV[a] && mergeV[b]) {
unsigned int markA, markB;
unsigned int ssssA, ssssB;
markA = result[a]&((1<<16)-1);
markB = result[b]&((1<<16)-1);
ssssA = result[a]>>16;
ssssB = result[b]>>16;
if(markA == markB) {
unsigned int diff = ssssA ^ ssssB;
if((diff&(-diff)) == diff) {
unsigned int markC = (markA) ^ diff;
unsigned int ssssC = min(ssssA, ssssB);
ok = 1;
combine[result[a]]++;
combine[result[b]]++;
V = (ssssC<<16)|markC;
combineN[(ssssC<<16)|markC] = i;
result[i] = (ssssC<<16)|markC;
mergeV[i] = 1;
}
}
}
}
}
if(ok)
combine[V]++;
}
set< int, cmp > output[20];
for(map<unsigned int, int>::iterator it = combine.begin();
it != combine.end(); it++) {
if(it->second > 1)
continue;
/*printf("merge %d: count %d \n", it->first, it->second);*/
unsigned int markA;
unsigned int ssssA;
markA = it->first&((1<<16)-1);
ssssA = it->first>>16;
int cc = combineN[it->first];
/*for(int i = 0; i < 4; i++) {
printf("%d ", (markA>>i)&1);
}
puts(" e ");
for(int i = 0; i < 4; i++) {
printf("%d ", (ssssA>>i)&1);
}
puts("");
for(int i = 0; i < 16; i++) {
if((cc>>i)&1)
printf("%d ", i);
}
puts("");*/
int osize = 0;
for(int i = 0; i < 16; i++) {
if((cc>>i)&1)
osize++;
}
output[osize].insert(cc);
}
int f = 0;
for(int k = 16; k >= 0; k--)
for(set< int >::iterator it = output[k].begin();
it != output[k].end(); it++) {
int cc = (*it);
if(f) printf(",");
f = 1;
putchar('(');
int f2 = 0;
for(int i = 0; i < 16; i++) {
if((cc>>i)&1) {
if(f2) printf(", ");
f2 = 1;
printf("%d", i);
}
}
putchar(')');
}
puts("");
}
int main() {
char in[1024];
while(gets(in)) {
int error = 0;
for(int i = 0; in[i]; i++) {
if(in[i] == ')')
in[i] = ' ';
else if(in[i] == '(')
in[i] = ' ';
else if(in[i] == ',')
in[i] = ' ';
else if(in[i] <= '9' && in[i] >= '0')
continue;
else
error = 1;
}
stringstream sin(in);
int number;
n = 0;
while(sin >> number) {
A[n++] = number;
}
if(n >= 1024)
while(1);
sort(A, A+n);
int ok = 1;
for(int i = 0; i < n; i++)
if(A[i] < 0 || A[i] > 15)
ok = 0;
if(ok == 0 || error) {
printf("Invalid input format");
continue;
}/*
printf("%d\n", n);
for(int i = 0; i < n; i++)
printf("%d\n", A[i]);*/
solv();
}
return 0;
}
/*
(0,2,5,8,10)
(0,2,3,5,7,8,9,10,11,13,15)
(0,1,2,5,6,7,8,9,10,14)
(0,1,2,4,5,6,8,9,12,13,14)
(0,1,2,5,6,7,8,9,10,16)
*/

Problem D Binary String

雖然詢問每個參數最大上限後,發現在 m = 100 的情況下,窮舉有點刺激,但是題目卻是要求輸出每一種組合,所以想必組合也不會太多,所以直接亂來吧!

至於以下代碼的正確性就交給神吧,反正都是亂做過的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int n, m, s_ones;
char s[105], ret[105];
int slen = 0;
void dfs(int idx, int ones, int has) {
if(ones > m)
return;
if(has == 0 && idx - slen >= 0) {
int ok = 1;
for(int i = idx - slen, j = 0; j < slen; j++, i++) {
ok &= ret[i] == s[j];
}
if(ok)
has = 1;
}
if(idx == n) {
if(ones != m || !has)
return;
ret[n] = '\0';
puts(ret);
return;
}
ret[idx] = '0';
dfs(idx+1, ones, has);
ret[idx] = '1';
dfs(idx+1, ones+1, has);
}
int main() {
while(scanf("%d %d %s", &n, &m, s) == 3) {
s_ones = 0;
for(int i = 0; s[i]; i++)
s_ones += s[i] == '1';
slen = strlen(s);
dfs(0, 0, 0);
}
return 0;
}

Problem E Digits Count

這題在 UVa 見過,但是要在比賽中打出來,卻卡死兩個很久沒用腦的人,直到鎖版 (最後一個小時) 才湊出來。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int mpow(int n, int m) {
int ret = 1;
for(int i = 1; i <= m; i++)
ret *= n;
return ret;
}
void calc(int n, int cnt[]) {
if(n <= 0)
return;
//printf("%d\n", n);
char buf[105];
sprintf(buf, "%d", n);
int len = strlen(buf);
int prev = 0, suffix;
calc(mpow(10, len-1)-1, cnt);
//for(int i = 0; i < 10; i++)
// cnt[i] = 0;
int prev10 = 1;
for(int i = 0; i < len; i++) {
int d = buf[i] - '0';
sscanf(buf+i+1, "%d", &suffix);
if(i != len-1)
cnt[d] += suffix + 1;
else
cnt[d]++;
if(i != 0)
cnt[d] += (prev - prev10/10) * mpow(10, len-i-1);
// pritnf("%d \n", );
// puts("");
for(int j = i == 0; j < 10; j++) {
if(j == d) continue;
if(j < d) {
if(prev > 0) {
cnt[j] += (prev - prev10/10 + 1) * mpow(10, len-i-1);
//printf("%d %d\n", j, (prev - prev10/10 + 1) * mpow(10, len-i-2));
} else {
cnt[j] += mpow(10, len-i-1);
//printf("%d %d\n", j, mpow(10, len-i-1));
}
} else {
if(prev > 0 && prev - prev10/10 > 0) {
cnt[j] += (prev - prev10/10) * mpow(10, len-i-1);
//printf("%d %d\n", j, (prev - prev10/10 + 1) * mpow(10, len-i-2));
}
}
}
prev10 *= 10;
prev = prev * 10 + d;
}
/*for(int i = 0; i < 10; i++)
printf("%d ", cnt[i]);
puts("");*/
}
void brute(int n) {
int cnt[10] = {};
char buf[105];
for(int i = 1; i <= n; i++) {
sprintf(buf, "%d", i);
for(int j = 0; buf[j]; j++)
cnt[buf[j]-'0']++;
}
for(int i = 0; i < 10; i++)
printf("%d ", cnt[i]);
puts("");
}
int main() {
int l, r;
/*while(scanf("%d", &l) == 1) {
brute(l);
int cnt[10] = {};
calc(l, cnt);
for(int i = 0; i < 10; i++)
printf("%d ", cnt[i]);
puts("");
}*/
while(scanf("%d %d", &l, &r) == 2) {
if(l == 0 && r == 0)
break;
int A[10] = {}, B[10] = {};
calc(l-1, A);
calc(r, B);
for(int i = 0; i < 10; i++)
printf("%d%c", B[i] - A[i], i == 9 ? '\n' : ' ');
}
return 0;
}

Problem F Math Problem

大數二分開 n 方,根據別組的討論,才發現數字其實還挺小的,用 double 型態做 log 運算即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
public class A {
public static void main(String args[]) throws Exception { // µ{¦¡¶i¤JÂI
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int n = cin.nextInt();
String p = cin.next();
if(n == 1) {
System.out.println(p);
continue;
}
BigInteger bigp = new BigInteger(p);
BigInteger l = BigInteger.ZERO;
BigInteger r = new BigInteger(p);
BigInteger m = l, mid, mmid;
while(l.compareTo(r) <= 0) {
mid = l.add(r).shiftRight(1);
mmid = mid.pow(n);
if(mmid.compareTo(bigp) <= 0) {
l = mid.add(BigInteger.ONE);
m = mid;
} else
r = mid.subtract(BigInteger.ONE);
}
System.out.println(m);
}
}
}

Problem G Better Method

聽說是曾經的萬年測試題,這次難得變成主角,肯定是想要每組至少都能帶一題回去。跟 ICPC 一樣的設計方式呢。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <algorithm>
using namespace std;
int f(int n) {
int ret = n;
while(n >= 3) {
ret += n/3;
n = n%3 + n/3;
}
return ret;
}
int main() {
int n;
while(scanf("%d", &n) == 1) {
int v = max(f(n), f(n+1)-1);
printf("%d\n", v);
}
return 0;
}

Problem H K-Anonymous Sequence

本次第二難的題目,但比賽時也是用假解過的,實質為單調對列,可以在 O(n) 時間內完成。至於假解的方式就不方便提供。

賽後

UVa 2000+ 才到這了,腦部硬體的差距就是如此地遙遠,即使捨去其他應用軟體,仍然趕不上嗎?

1
2
3
4
5
6
7
8
9
10
Rank Name Solved Time A B C D E F G H Total att/solv
1 team22 6 608 1/11 2/58 0/-- 3/141 1/221 1/50 1/67 5/-- 14/6
2 team2 6 844 2/32 7/-- 14/-- 1/108 1/244 1/19 1/11 8/270 35/6
3 team4 5 530 1/7 1/281 26/-- 1/217 1/-- 1/9 1/16 0/-- 32/5
4 team17 5 698 2/13 1/105 1/-- 4/296 0/-- 1/167 1/37 3/-- 13/5
5 team1 5 958 3/286 0/-- 4/240 4/-- 1/178 1/69 1/85 0/-- 14/5
6 team12 4 177 1/11 0/-- 3/-- 0/-- 1/138 1/17 1/11 0/-- 7/4
7 team3 4 359 1/108 0/-- 5/-- 0/-- 1/188 1/35 1/28 0/-- 9/4
8 team23 4 776 1/12 7/278 0/-- 0/-- 0/-- 1/57 5/229 0/-- 14/4
9 team20 4 815 8/131 4/159 0/-- 0/-- 0/-- 1/164 1/161 0/-- 14/4
1
2
3
4
5
6
7
名次 學校學系 隊名
第一名 國立成功大學資訊工程學系 ItsNotCode
第二名 國立中央大學資訊工程學系 Morri$
第三名 國立清華大學資訊工程學系 ISeaTeL
佳作 國立成功大學資訊工程學系 Insert
佳作 國立臺北大學資訊工程學系 Forward Thinking
佳作 國立清華大學資訊工程學系 JustInTime
Read More +

HTML5 Music Player (本地拖曳撥放)

代碼起源

tommy351 提供的。基於 HTML5 和 JQuery 運行的撥放器,HTML5 支持 .mp3, .wav, .ogg 這三個種音樂格式的撥放。

HTML5 <audio> 支持音樂撥放,撥放種類有限,而且 HTML5 不知道穩定了沒。

  • 本次挑戰的項目
    • 增加 拖曳檔案 的撥放
    • 拖曳檔案 和 拖曳資料夾 的摸索
    • HTML5 圍觀

修改

demo
如上圖,最後一個檔案 mo - 45. not yet.mp3 是拖曳上傳的內容。

歷程

  • 增加本地拖曳撥放,操作方式為將本地 mp3 檔案上傳

檔案能知道的資訊有限

  • name 取得檔案名稱,如果需要做副檔名檢查,可利用它。
  • size 取得檔案大小 (bytes)。
  • type 取得檔案的 MIME 型別 (若無法對應會傳回空白)。

因為安全性,所以得不到路徑資訊,也就是不能隨便去掃描別人的本地資料。因此要完成資料夾下的所有檔案獲取會有困難。

其實瀏覽器本上就會支持檔案拖曳,並且在新分頁上顯示資訊,如果要避免瀏覽器自己開啟檔案,則使用 evt.stopPropagation() 將 drag 相關事件關閉,也就是說在當前頁面的 drag 事件都不會被瀏覽器知曉。

後記

  • 對於 .mp3 檔案要自動獲得專輯封面可能嗎?
    請參考 這裡

    1
    2
    3
    4
    5
    6
    7
    8
    Field Length Offsets
    Tag 3 0-2
    Songname 30 3-32
    Artist 30 33-62
    Album 30 63-92
    Year 4 93-96
    Comment 30 97-126
    Genre 1 127

    要自己擠去 parsing 這些資訊還是算了吧。WRYYYYY

  • 對於資料夾整包拖曳操作?HTML5 drag upload folder
    在寫這篇的時候,網路上有 demo,但是只有在 chrome 21 下才有支持,看起來是從瀏覽器 ( 本地軟件 ) 來協助遍歷資料夾下的內容。不然是沒有權限去運行的。

  • 讀取的異步操作 ?
    是的,最近在編寫時常會遇到異步操作,也就是必須全用 callback 來完成,因為讀檔的資訊完成的 callback function 中並沒有 file.name 之類的資訊,如果適用 for(var i in files) 運行,會發生變數找不到的情況,因此用 $.each()reader.onload() 來完成這個操作。

    • onloadstart、onprogress、onload、onabort、onerror 和 onloadend 這幾個可以協助監控上傳資訊,也就是能知曉現在上傳進度 … 等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
var dropbox = document.getElementById("dropbox")
// init event handlers
dropbox.addEventListener("dragenter", dragEnter, false);
dropbox.addEventListener("dragexit", dragExit, false);
dropbox.addEventListener("dragover", dragOver, false);
dropbox.addEventListener("drop", drop, false);
// init the widgets
$("#progressbar").progressbar();
function dragEnter(evt) {
evt.stopPropagation();
evt.preventDefault();
}
function dragExit(evt) {
evt.stopPropagation();
evt.preventDefault();
}
function dragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
}
function drop(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files;
var count = files.length;
// Only call the handler if 1 or more files was dropped.
if (count > 0)
handleFiles(files);
}
function handleFiles(files) {
var mp3Files = $.map(files, function(f, i) {
return f.type.indexOf("audio/mp3") == 0 ? f : null;
});
$.each(mp3Files, function(i, file) {
document.getElementById("droplabel").innerHTML = "Processing " + file.name;
var reader = new FileReader();
reader.onload = function(evt) {
$('#playlist').append('<li>' + 'mo' + ' - ' + file.name + '</li>');
playlist.push({
title: file.name,
mp3: evt.target.result
});
$('#playlist li').each(function(i) {
var _i = i;
$(this).on('click', function() {
switchTrack(_i);
});
});
}
// init the reader event handlers
reader.onprogress = handleReaderProgress;
reader.onloadend = handleReaderLoadEnd;
reader.readAsDataURL(file);
});
}
function handleReaderProgress(evt) {
if (evt.lengthComputable) {
var loaded = (evt.loaded / evt.total);
$("#progressbar").progressbar({
value: loaded * 100
});
}
}
function handleReaderLoadEnd(evt) {
$("#progressbar").progressbar({
value: 100
});
}

最後

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title>Cover Art</title>
<link rel="stylesheet" href="css/stylesheets/style.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
</head>
<body>
<div id="playblock">
<div id="player">
<div class="cover"></div>
<div class="ctrl">
<div class="tag">
<strong>Title</strong>
<span class="artist">Artist</span>
<span class="album">Album</span>
</div>
<div class="control">
<div class="left">
<div class="rewind icon"></div>
<div class="playback icon"></div>
<div class="fastforward icon"></div>
</div>
<div class="volume right">
<div class="mute icon left"></div>
<div class="slider left">
<div class="pace"></div>
</div>
</div>
</div>
<div class="progress">
<div class="slider">
<div class="loaded"></div>
<div class="pace"></div>
</div>
<div class="timer left">0:00</div>
<div class="right">
<div class="repeat icon"></div>
<div class="shuffle icon"></div>
</div>
</div>
</div>
</div>
<div id="dropbox">
<div id="dropctrl">
<span id="droplabel">Drop mp3 file here...</span>
<div id="progressbar"></div>
</div>
<ul id="playlist"></ul>
</div>
</div>
<footer>
Copyright &copy; 2012 <a href="http://zespia.tw">SkyArrow</a>
</footer>
<script src="js/script.js"></script>
</body>
</html>

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
(function($) {
// Settings
var repeat = localStorage.repeat || 0,
shuffle = localStorage.shuffle || 'false',
continous = true,
autoplay = false,
playlist = [{
title: 'ふわふわ時間',
artist: '桜高軽音部(平沢唯、秋山澪、田井中律、琴吹紬)',
album: 'TVアニメ「けいおん!」劇中歌 - ふわふわ時間',
cover: 'http://dl.dropbox.com/u/5480889/coverart/cover/ふわふわ時間.jpg',
mp3: 'http://dl.dropbox.com/u/5480889/coverart/music/ふわふわ時間.mp3',
ogg: 'http://dl.dropbox.com/u/5480889/coverart/music/ふわふわ時間.ogg'
}, {
title: 'リップシンク',
artist: 'nano.RIPE',
album: '細胞キオク',
cover: 'http://dl.dropbox.com/u/5480889/coverart/cover/リップシンク.jpg',
mp3: 'http://dl.dropbox.com/u/5480889/coverart/music/リップシンク.mp3',
ogg: 'http://dl.dropbox.com/u/5480889/coverart/music/リップシンク.ogg'
}];
for (var i = 0; i < playlist.length; i++) {
var item = playlist[i];
$('#playlist').append('<li>' + item.artist + ' - ' + item.title + '</li>');
}
// Load playlist
var time = new Date(),
currentTrack = shuffle === 'true' ? time.getTime() % playlist.length : 0,
trigger = false,
audio, timeout, isPlaying, playCounts;
var play = function() {
audio.play();
$('.playback').addClass('playing');
timeout = setInterval(updateProgress, 500);
isPlaying = true;
}
var pause = function() {
audio.pause();
$('.playback').removeClass('playing');
clearInterval(updateProgress);
isPlaying = false;
}
// Update progress
var setProgress = function(value) {
var currentSec = parseInt(value % 60) < 10 ? '0' + parseInt(value % 60) : parseInt(value % 60),
ratio = value / audio.duration * 100;
$('.timer').html(parseInt(value / 60) + ':' + currentSec);
$('.progress .pace').css('width', ratio + '%');
$('.progress .slider a').css('left', ratio + '%');
}
var updateProgress = function() {
setProgress(audio.currentTime);
}
// Progress slider
$('.progress .slider').slider({
step: 0.1,
slide: function(event, ui) {
$(this).addClass('enable');
setProgress(audio.duration * ui.value / 100);
clearInterval(timeout);
},
stop: function(event, ui) {
audio.currentTime = audio.duration * ui.value / 100;
$(this).removeClass('enable');
timeout = setInterval(updateProgress, 500);
}
});
// Volume slider
var setVolume = function(value) {
audio.volume = localStorage.volume = value;
$('.volume .pace').css('width', value * 100 + '%');
$('.volume .slider a').css('left', value * 100 + '%');
}
var volume = localStorage.volume || 0.5;
$('.volume .slider').slider({
max: 1,
min: 0,
step: 0.01,
value: volume,
slide: function(event, ui) {
setVolume(ui.value);
$(this).addClass('enable');
$('.mute').removeClass('enable');
},
stop: function() {
$(this).removeClass('enable');
}
}).children('.pace').css('width', volume * 100 + '%');
$('.mute').click(function() {
if ($(this).hasClass('enable')) {
setVolume($(this).data('volume'));
$(this).removeClass('enable');
} else {
$(this).data('volume', audio.volume).addClass('enable');
setVolume(0);
}
});
// Switch track
var switchTrack = function(i) {
if (i < 0) {
track = currentTrack = playlist.length - 1;
} else if (i >= playlist.length) {
track = currentTrack = 0;
} else {
track = i;
}
$('audio').remove();
loadMusic(track);
if (isPlaying == true) play();
}
// Shuffle
var shufflePlay = function() {
var time = new Date(),
lastTrack = currentTrack;
currentTrack = time.getTime() % playlist.length;
if (lastTrack == currentTrack)++currentTrack;
switchTrack(currentTrack);
}
// Fire when track ended
var ended = function() {
pause();
audio.currentTime = 0;
playCounts++;
if (continous == true) isPlaying = true;
if (repeat == 1) {
play();
} else {
if (shuffle === 'true') {
shufflePlay();
} else {
if (repeat == 2) {
switchTrack(++currentTrack);
} else {
if (currentTrack < playlist.length) switchTrack(++currentTrack);
}
}
}
}
var beforeLoad = function() {
var endVal = this.seekable && this.seekable.length ? this.seekable.end(0) : 0;
$('.progress .loaded').css('width', (100 / (this.duration || 1) * endVal) + '%');
}
// Fire when track loaded completely
var afterLoad = function() {
if (autoplay == true) play();
}
// Load track
var loadMusic = function(i) {
var item = playlist[i],
newaudio = $('<audio>').html('<source src="' + item.mp3 + '"><source src="' + item.ogg + '">').appendTo('#player');
$('.cover').html('<img src="' + item.cover + '" alt="' + item.album + '">');
$('.tag').html('<strong>' + item.title + '</strong><span class="artist">' + item.artist + '</span><span class="album">' + item.album + '</span>');
$('#playlist li').removeClass('playing').eq(i).addClass('playing');
audio = newaudio[0];
audio.volume = $('.mute').hasClass('enable') ? 0 : volume;
audio.addEventListener('progress', beforeLoad, false);
audio.addEventListener('durationchange', beforeLoad, false);
audio.addEventListener('canplay', afterLoad, false);
audio.addEventListener('ended', ended, false);
}
loadMusic(currentTrack);
$('.playback').on('click', function() {
if ($(this).hasClass('playing')) {
pause();
} else {
play();
}
});
$('.rewind').on('click', function() {
if (shuffle === 'true') {
shufflePlay();
} else {
switchTrack(--currentTrack);
}
});
$('.fastforward').on('click', function() {
if (shuffle === 'true') {
shufflePlay();
} else {
switchTrack(++currentTrack);
}
});
$('#playlist li').each(function(i) {
var _i = i;
$(this).on('click', function() {
switchTrack(_i);
});
});
if (shuffle === 'true') $('.shuffle').addClass('enable');
if (repeat == 1) {
$('.repeat').addClass('once');
} else if (repeat == 2) {
$('.repeat').addClass('all');
}
$('.repeat').on('click', function() {
if ($(this).hasClass('once')) {
repeat = localStorage.repeat = 2;
$(this).removeClass('once').addClass('all');
} else if ($(this).hasClass('all')) {
repeat = localStorage.repeat = 0;
$(this).removeClass('all');
} else {
repeat = localStorage.repeat = 1;
$(this).addClass('once');
}
});
$('.shuffle').on('click', function() {
if ($(this).hasClass('enable')) {
shuffle = localStorage.shuffle = 'false';
$(this).removeClass('enable');
} else {
shuffle = localStorage.shuffle = 'true';
$(this).addClass('enable');
}
});
var dropbox = document.getElementById("dropbox")
// init event handlers
dropbox.addEventListener("dragenter", dragEnter, false);
dropbox.addEventListener("dragexit", dragExit, false);
dropbox.addEventListener("dragover", dragOver, false);
dropbox.addEventListener("drop", drop, false);
// init the widgets
$("#progressbar").progressbar();
function dragEnter(evt) {
evt.stopPropagation();
evt.preventDefault();
}
function dragExit(evt) {
evt.stopPropagation();
evt.preventDefault();
}
function dragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
}
function drop(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files;
var count = files.length;
// Only call the handler if 1 or more files was dropped.
if (count > 0)
handleFiles(files);
}
function handleFiles(files) {
var mp3Files = $.map(files, function(f, i) {
return f.type.indexOf("audio/mp3") == 0 ? f : null;
});
$.each(mp3Files, function(i, file) {
document.getElementById("droplabel").innerHTML = "Processing " + file.name;
var reader = new FileReader();
reader.onload = function(evt) {
$('#playlist').append('<li>' + 'mo' + ' - ' + file.name + '</li>');
playlist.push({
title: file.name,
mp3: evt.target.result
});
$('#playlist li').each(function(i) {
var _i = i;
$(this).on('click', function() {
switchTrack(_i);
});
});
}
// init the reader event handlers
reader.onprogress = handleReaderProgress;
reader.onloadend = handleReaderLoadEnd;
reader.readAsDataURL(file);
});
}
function handleReaderProgress(evt) {
if (evt.lengthComputable) {
var loaded = (evt.loaded / evt.total);
$("#progressbar").progressbar({
value: loaded * 100
});
}
}
function handleReaderLoadEnd(evt) {
$("#progressbar").progressbar({
value: 100
});
}
})(jQuery);
Read More +

程序设计实习 MOOC Week 6(待補)

前提概要

這一道題目,照理來講是一版一版慢慢加強,但是突然接收到巨噁模擬題。在很有耐心看完後,看起來是不得度使用物件導向的多形來模擬,不然程式代碼會寫得非常難看,難看也倒還好,只是怕寫不出來。

不過礙於時間關係,寫到一半還是放棄了,於是附加的代碼是 失敗 的。

卡在 RE 狀態,明明本地端測試不會有噴出 RE 資訊,上傳卻發生了 RE,暫時沒有辦法去解決。
題目來源

A - 魔兽世界终极版

題目

总时间限制: 2000ms 内存限制: 65536kB

描述

魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市,城市从西向东依次编号为1,2,3 …. N ( N <= 20 )。红魔军的司令部算作编号为0的城市,蓝魔军的司令部算作编号为N+1的城市。司令部有生命元,用于制造武士。

两军的司令部都会制造武士。武士一共有 dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。

双方的武士编号都是从1开始计算。红方制造出来的第 n 个武士,编号就是n。同样,蓝方制造出来的第 n 个武士,编号也是n。

武士在刚降生的时候有一个初始的生命值,生命值在战斗中会发生变化,如果生命值减少到0(生命值变为负数时应当做变为0处理),则武士死亡(消失)。

有的武士可以拥有武器。武器有三种,sword, bomb,和arrow,编号分别为0,1,2。

武士降生后就朝对方司令部走,在经过的城市如果遇到敌人(同一时刻每个城市最多只可能有1个蓝武士和一个红武士),就会发生战斗。每次战斗只有一方发起主动进攻一次。被攻击者生命值会减去进攻者的攻击力值和进攻者手中sword的攻击力值。被进攻者若没死,就会发起反击,被反击者的生命值要减去反击者攻击力值的一半(去尾取整)和反击者手中sword的攻击力值。反击可能致敌人于死地。

如果武士在战斗中杀死敌人(不论是主动进攻杀死还是反击杀死),则其司令部会立即向其发送8个生命元作为奖励,使其生命值增加8。当然前提是司令部得有8个生命元。如果司令部的生命元不足以奖励所有的武士,则优先奖励距离敌方司令部近的武士。

如果某武士在某城市的战斗中杀死了敌人,则该武士的司令部立即取得该城市中所有的生命元。注意,司令部总是先完成全部奖励工作,然后才开始从各个打了胜仗的城市回收生命元。对于因司令部生命元不足而领不到奖励的武士,司令部也不会在取得战利品生命元后为其补发奖励。

如果一次战斗的结果是双方都幸存(平局),则双方都不能拿走发生战斗的城市的生命元。

城市可以插旗子,一开始所有城市都没有旗子。在插红旗的城市,以及编号为奇数的无旗城市,由红武士主动发起进攻。在插蓝旗的城市,以及编号为偶数的无旗城市,由蓝武士主动发起进攻。

当某个城市有连续两场战斗都是同一方的武士杀死敌人(两场战斗之间如果有若干个战斗时刻并没有发生战斗,则这两场战斗仍然算是连续的;但如果中间有平局的战斗,就不算连续了) ,那么该城市就会插上胜方的旗帜,若原来插着败方的旗帜,则败方旗帜落下。旗帜一旦插上,就一直插着,直到被敌人更换。一个城市最多只能插一面旗帜,旗帜没被敌人更换前,也不会再次插同颜色的旗。

各种武器有其特点:

sword武器的初始攻击力为拥有它的武士的攻击力的20%(去尾取整)。但是sword每经过一次战斗(不论是主动攻击还是反击),就会变钝,攻击力变为本次战斗前的80% (去尾取整)。sword攻击力变为0时,视为武士失去了sword。如果武士降生时得到了一个初始攻击力为0的sword,则视为武士没有sword.

arrow有一个攻击力值R。如果下一步要走到的城市有敌人,那么拥有arrow的武士就会放箭攻击下一个城市的敌人(不能攻击对方司令部里的敌人)而不被还击。arrow使敌人的生命值减少R,若减至小于等于0,则敌人被杀死。arrow使用3次后即被耗尽,武士失去arrow。两个相邻的武士可能同时放箭把对方射死。

拥有bomb的武士,在战斗开始前如果判断自己将被杀死(不论主动攻击敌人,或者被敌人主动攻击都可能导致自己被杀死,而且假设武士可以知道敌人的攻击力和生命值),那么就会使用bomb和敌人同归于尽。武士不预测对方是否会使用bomb。

武士使用bomb和敌人同归于尽的情况下,不算是一场战斗,双方都不能拿走城市的生命元,也不影响城市的旗帜。

不同的武士有不同的特点。

dragon可以拥有一件武器。编号为n的dragon降生时即获得编号为 n%3 的武器。dragon还有“士气”这个属性,是个浮点数,其值为它降生后其司令部剩余生命元的数量除以造dragon所需的生命元数量。dragon 在一次在它主动进攻的战斗结束后,如果还没有战死,而且士气值大于0.8,就会欢呼。dragon每取得一次战斗的胜利(敌人被杀死),士气就会增加0.2,每经历一次未能获胜的战斗,士气值就会减少0.2。士气增减发生在欢呼之前。

ninjia可以拥有两件武器。编号为n的ninjia降生时即获得编号为 n%3 和 (n+1)%3的武器。ninja 挨打了也从不反击敌人。

iceman有一件武器。编号为n的iceman降生时即获得编号为 n%3 的武器。iceman 每前进两步,在第2步完成的时候,生命值会减少9,攻击力会增加20。但是若生命值减9后会小于等于0,则生命值不减9,而是变为1。即iceman不会因走多了而死。

lion 有“忠诚度”这个属性,其初始值等于它降生之后其司令部剩余生命元的数目。每经过一场未能杀死敌人的战斗,忠诚度就降低K。忠诚度降至0或0以下,则该lion逃离战场,永远消失。但是已经到达敌人司令部的lion不会逃跑。Lion在己方司令部可能逃跑。lion 若是战死,则其战斗前的生命值就会转移到对手身上。所谓“战斗前”,就是每个小时的40分前的一瞬间。

wolf降生时没有武器,但是在战斗中如果获胜(杀死敌人),就会缴获敌人的武器,但自己已有的武器就不缴获了。被缴获的武器当然不能算新的,已经被用到什么样了,就是什么样的。

以下是不同时间会发生的不同事件:

在每个整点,即每个小时的第0分, 双方的司令部中各有一个武士降生。

红方司令部按照 iceman、lion、wolf、ninja、dragon 的顺序制造武士。

蓝方司令部按照 lion、dragon、ninja、iceman、wolf 的顺序制造武士。

制造武士需要生命元。

制造一个初始生命值为 m 的武士,司令部中的生命元就要减少 m 个。

如果司令部中的生命元不足以制造某武士,那么司令部就等待,直到获得足够生命元后的第一个整点,才制造该武士。例如,在2:00,红方司令部本该制造一个 wolf ,如果此时生命元不足,那么就会等待,直到生命元足够后的下一个整点,才制造一个 wolf。

在每个小时的第5分,该逃跑的lion就在这一时刻逃跑了。

在每个小时的第10分:所有的武士朝敌人司令部方向前进一步。即从己方司令部走到相邻城市,或从一个城市走到下一个城市。或从和敌军司令部相邻的城市到达敌军司令部。

在每个小时的第20分:每个城市产出10个生命元。生命元留在城市,直到被武士取走。

在每个小时的第30分:如果某个城市中只有一个武士,那么该武士取走该城市中的所有生命元,并立即将这些生命元传送到其所属的司令部。

在每个小时的第35分,拥有arrow的武士放箭,对敌人造成伤害。放箭事件应算发生在箭发出的城市。注意,放箭不算是战斗,因此放箭的武士不会得到任何好处。武士在没有敌人的城市被箭射死也不影响其所在城市的旗帜更换情况。

在每个小时的第38分,拥有bomb的武士评估是否应该使用bomb。如果是,就用bomb和敌人同归于尽。

在每个小时的第40分:在有两个武士的城市,会发生战斗。 如果敌人在5分钟前已经被飞来的arrow射死,那么仍然视为发生了一场战斗,而且存活者视为获得了战斗的胜利。此情况下不会有“武士主动攻击”,“武士反击”,“武士战死”的事件发生,但战斗胜利后应该发生的事情都会发生。如Wolf一样能缴获武器,旗帜也可能更换,等等。在此情况下,Dragon同样会通过判断是否应该轮到自己主动攻击来决定是否欢呼。

在每个小时的第50分,司令部报告它拥有的生命元数量。

在每个小时的第55分,每个武士报告其拥有的武器情况。

武士到达对方司令部后就算完成任务了,从此就呆在那里无所事事。

任何一方的司令部里若是出现了2个敌人,则认为该司令部已被敌人占领。

任何一方的司令部被敌人占领,则战争结束。战争结束之后就不会发生任何事情了。

给定一个时间,要求你将从0点0分开始到此时间为止的所有事件按顺序输出。事件及其对应的输出样例如下:

1) 武士降生

输出样例: 000:00 blue lion 1 born

表示在 0点0分,编号为1的蓝魔lion武士降生
如果造出的是dragon,那么还要多输出一行,例:

000:00 blue dragon 1 born
Its morale is 23.34

表示该该dragon降生时士气是23. 34(四舍五入到小数点后两位)

如果造出的是lion,那么还要多输出一行,例:
000:00 blue lion 1 born
Its loyalty is 24

表示该lion降生时的忠诚度是24

2) lion逃跑

输出样例: 000:05 blue lion 1 ran away
表示在 0点5分,编号为1的蓝魔lion武士逃走

3) 武士前进到某一城市

输出样例: 000:10 red iceman 1 marched to city 1 with 20 elements and force 30
表示在 0点10分,红魔1号武士iceman前进到1号城市,此时他生命值为20,攻击力为30
对于iceman,输出的生命值和攻击力应该是变化后的数值

4)武士放箭

输出样例: 000:35 blue dragon 1 shot
表示在 0点35分,编号为1的蓝魔dragon武士射出一支箭。如果射出的箭杀死了敌人,则应如下输出:
000:35 blue dragon 1 shot and killed red lion 4
表示在 0点35分,编号为1的蓝魔dragon武士射出一支箭,杀死了编号为4的红魔lion。

5)武士使用bomb

输出样例: 000:38 blue dragon 1 used a bomb and killed red lion 7
表示在 0点38分,编号为1的蓝魔dragon武士用炸弹和编号为7的红魔lion同归于尽。

6) 武士主动进攻

输出样例:000:40 red iceman 1 attacked blue lion 1 in city 1 with 20 elements and force 30
表示在0点40分,1号城市中,红魔1号武士iceman 进攻蓝魔1号武士lion,在发起进攻前,红魔1号武士iceman生命值为20,攻击力为 30

7) 武士反击

输出样例:001:40 blue dragon 2 fought back against red lion 2 in city 1
表示在1点40分,1号城市中,蓝魔2号武士dragon反击红魔2号武士lion

8) 武士战死

输出样例:001:40 red lion 2 was killed in city 1
被箭射死的武士就不会有这一条输出。

9) 武士欢呼

输出样例:003:40 blue dragon 2 yelled in city 4

10) 武士获取生命元( elements )

输出样例:001:40 blue dragon 2 earned 10 elements for his headquarter

11) 旗帜升起

输出样例:004:40 blue flag raised in city 4

12) 武士抵达敌军司令部

输出样例:001:10 red iceman 1 reached blue headquarter with 20 elements and force 30
(此时他生命值为20,攻击力为30)对于iceman,输出的生命值和攻击力应该是变化后的数值

13) 司令部被占领

输出样例:003:10 blue headquarter was taken

14)司令部报告生命元数量

000:50 100 elements in red headquarter
000:50 120 elements in blue headquarter
表示在0点50分,红方司令部有100个生命元,蓝方有120个

15)武士报告武器情况

000:55 blue wolf 2 has arrow(2),bomb,sword(23)
000:55 blue wolf 4 has no weapon
000:55 blue wolf 5 has sword(20)
表示在0点55分,蓝魔2号武士wolf有一支arrow(这支arrow还可以用2次),一个bomb,还有一支攻击力为23的sword。
蓝魔4号武士wolf没武器。
蓝魔5号武士wolf有一支攻击力为20的sword。
交代武器情况时,次序依次是:arrow,bomb,sword。如果没有某种武器,某种武器就不用提。报告时,先按从西向东的顺序所有的红武士报告,然后再从西向东所有的蓝武士报告。

输出事件时:

首先按时间顺序输出;

同一时间发生的事件,按发生地点从西向东依次输出. 武士前进的事件, 算是发生在目的地。

在一次战斗中有可能发生上面的 6 至 11 号事件。这些事件都算同时发生,其时间就是战斗开始时间。一次战斗中的这些事件,序号小的应该先输出。

两个武士同时抵达同一城市,则先输出红武士的前进事件,后输出蓝武士的。

显然,13号事件发生之前的一瞬间一定发生了12号事件。输出时,这两件事算同一时间发生,但是应先输出12号事件

虽然任何一方的司令部被占领之后,就不会有任何事情发生了。但和司令部被占领同时发生的事件,全都要输出。

输入

第一行是t,代表测试数据组数
每组样例共三行。
第一行,五个整数 M,N,R,K, T。其含义为:

每个司令部一开始都有M个生命元( 1 <= M <= 10000)
两个司令部之间一共有N个城市( 1 <= N <= 20 )
arrow的攻击力是R
lion每经过一场未能杀死敌人的战斗,忠诚度就降低K。
要求输出从0时0分开始,到时间T为止(包括T) 的所有事件。T以分钟为单位,0 <= T <= 5000

第二行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的初始生命值。它们都大于0小于等于10000

第三行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的攻击力。它们都大于0小于等于10000

输出

对每组数据,先输出一行:
Case n:
如对第一组数据就输出 Case1:
然后按恰当的顺序和格式输出到时间T为止发生的所有事件。每个事件都以事件发生的时间开头,时间格式是“时: 分”,“时”有三位,“分”有两位。

样例输入

1
20 1 10 10 1000
20 20 30 10 20
5 5 5 5 5

样例输出

Case 1:
000:00 blue lion 1 born
Its loyalty is 10
000:10 blue lion 1 marched to city 1 with 10 elements and force 5
000:30 blue lion 1 earned 10 elements for his headquarter
000:50 20 elements in red headquarter
000:50 20 elements in blue headquarter
000:55 blue lion 1 has no weapon
001:00 blue dragon 2 born
Its morale is 0.00
001:10 blue lion 1 reached red headquarter with 10 elements and force 5
001:10 blue dragon 2 marched to city 1 with 20 elements and force 5
001:30 blue dragon 2 earned 10 elements for his headquarter
001:50 20 elements in red headquarter
001:50 10 elements in blue headquarter
001:55 blue lion 1 has no weapon
001:55 blue dragon 2 has arrow(3)
002:10 blue dragon 2 reached red headquarter with 20 elements and force 5
002:10 red headquarter was taken

失敗代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
#include <stdio.h>
#include <algorithm>
#include <map>
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
class Info {
public:
static int M, N, R, K, T;
static map<string, int> HP, ATK;
static string Mkind[];
static string Rkind[];
static string Bkind[];
};
int Info::M = 0, Info::N = 0, Info::R = 0, Info::K = 0, Info::T = 0;
map<string, int> Info::HP, Info::ATK;
string Info::Mkind[] = {"dragon", "ninja", "iceman", "lion", "wolf"};
string Info::Rkind[] = {"dragon", "iceman", "lion", "wolf", "ninja"};
string Info::Bkind[] = {"wolf", "lion", "dragon", "ninja", "iceman"};
class Weapon {
public:
virtual void show() {};
virtual int getMeleeAttack() {
return 0;
};
virtual int actMeleeAttack() {
return 0;
};
virtual int getRangeAttack() {
return 0;
}
virtual int actRangeAttack() {
return 0;
}
virtual int getBombAttack() {
return 0;
}
virtual int actBombAttack() {
return 0;
}
};
class Sword: public Weapon {
public:
int attack;
Sword(int _attack): attack(_attack) {
}
int getMeleeAttack() {
return attack;
}
int actMeleeAttack() {
attack = attack * 8 / 10;
return attack > 0;
}
void show() {
printf("sword(%d)", attack);
}
};
class Arrow: public Weapon {
public:
int R, usedTime;
Arrow(int _R): R(_R) {
usedTime = 0;
}
int getRangeAttack() {
return usedTime < 3 ? R : 0;
}
int actRangeAttack() {
usedTime++;
return usedTime >= 3;
}
void show() {
printf("arrow(%d)", 3 - usedTime);
}
};
class Bomb: public Weapon {
public:
Bomb() {
}
int getBombAttack() {
return 1;
}
void show() {
printf("bomb");
}
};
class WeaponFactory {
public:
static Weapon* build(int n, int attack) {
if(n == 0) {
if(attack / 5 <= 0)
return NULL;
return new Sword(attack/5);
}
else if(n == 2)
return new Arrow(Info::R);
else
return new Bomb();
}
};
class Warrior {
public:
int n;
int life;
Warrior(int _n, int _life): n(_n), life(_life) {
}
virtual void show() {};
virtual void showName() {};
virtual void showWeapon() {};
virtual int getAttack() {return 0;}
virtual int getFled() {return 0;}
virtual int getMeleeAttack() {return 0;}
virtual void actMeleeAttack() {}
virtual int getBackAttack() {return 0;}
virtual void actBackAttack() {}
virtual void move() {};
virtual void actRangeAttack(Warrior* o) {};
};
class Dragon: public Warrior {
public:
Weapon *weapon;
float morale;
Dragon(int _n, int _life, float _morale): Warrior(_n, _life), morale(_morale) {
weapon = WeaponFactory::build(n%3, Info::ATK["dragon"]);
}
void show() {
printf("dragon %d born\n", n);
printf("Its morale is %.2f\n", morale);
}
void showName() {
printf("dragon %d", n);
}
void showWeapon() {
if(weapon != NULL)
weapon->show();
else
printf("no weapon");
}
int getAttack() {
return Info::ATK["dragon"];
}
int getMeleeAttack() {
int m = 0;
if(weapon != NULL)
m = weapon->getMeleeAttack();
return getAttack() + m;
}
int getBackAttack() {
int m = 0;
if(weapon != NULL)
m = weapon->getMeleeAttack();
return getAttack()/2 + m;
}
void actMeleeAttack() {
if(weapon != NULL) {
int f = weapon->actMeleeAttack();
if(f == 0) {
delete weapon;
weapon = NULL;
}
}
}
void actBackAttack() {
actMeleeAttack();
}
void actRangeAttack(Warrior* o) {
if(weapon != NULL) {
o->life -= weapon->getRangeAttack();
int f = weapon->actRangeAttack();
if(f == 1) {
delete weapon;
weapon = NULL;
}
}
}
};
class Ninja: public Warrior {
public:
Weapon *weapon[2];
Ninja(int _n, int _life): Warrior(_n, _life) {
weapon[0] = WeaponFactory::build(n%3, Info::ATK["ninja"]);
weapon[1] = WeaponFactory::build((n+1)%3, Info::ATK["ninja"]);
}
void show() {
printf("ninja %d born\n", n);
}
void showName() {
printf("ninja %d", n);
}
void showWeapon() {
int f1 = n%3, f2 = (n+1)%3, f = 0;
if(f1 < f2) {
if(weapon[0] != NULL)
weapon[0]->show(), f++;
if(f) putchar(',');
if(weapon[1] != NULL)
weapon[1]->show(), f++;
} else {
if(weapon[1] != NULL)
weapon[1]->show(), f++;
if(f) putchar(',');
if(weapon[0] != NULL)
weapon[0]->show(), f++;
}
if(f == 0)
printf("no weapon");
}
int getAttack() {
return Info::ATK["ninja"];
}
int getMeleeAttack() {
int m = 0;
if(weapon[0] != NULL)
m += weapon[0]->getMeleeAttack();
if(weapon[1] != NULL)
m += weapon[1]->getMeleeAttack();
return getAttack() + m;
}
int getBackAttack() {
int m = 0;
if(weapon[0] != NULL)
m += weapon[0]->getMeleeAttack();
if(weapon[1] != NULL)
m += weapon[1]->getMeleeAttack();
return getAttack()/2 + m;
}
void actMeleeAttack() {
if(weapon[0] != NULL) {
int f = weapon[0]->actMeleeAttack();
if(f == 0) {
delete weapon[0];
weapon[0] = NULL;
}
}
if(weapon[1] != NULL) {
int f = weapon[1]->actMeleeAttack();
if(f == 0) {
delete weapon[1];
weapon[1] = NULL;
}
}
}
void actBackAttack() {
actMeleeAttack();
}
void actRangeAttack(Warrior* o) {
for(int i = 0; i < 2; i++) {
if(weapon[i] != NULL) {
o->life -= weapon[i]->getRangeAttack();
int f = weapon[i]->actRangeAttack();
if(f == 1)
weapon[i] = NULL;
}
}
}
};
class Iceman: public Warrior {
public:
Weapon *weapon;
int move_count;
int attack;
Iceman(int _n, int _life): Warrior(_n, _life) {
weapon = WeaponFactory::build(n%3, Info::ATK["iceman"]);
move_count = 0;
attack = Info::ATK["iceman"];
}
void show(){
printf("iceman %d born\n", n);
}
void showName() {
printf("iceman %d", n);
}
void showWeapon() {
if(weapon != NULL)
weapon->show();
else
printf("no weapon");
}
int getAttack() {
return attack;
}
int getMeleeAttack() {
int m = 0;
if(weapon != NULL)
m = weapon->getMeleeAttack();
return getAttack() + m;
}
int getBackAttack() {
int m = 0;
if(weapon != NULL)
m = weapon->getMeleeAttack();
return getAttack()/2 + m;
}
void actMeleeAttack() {
if(weapon != NULL) {
int f = weapon->actMeleeAttack();
if(f == 0) {
delete weapon;
weapon = NULL;
}
}
}
void actBackAttack() {
actMeleeAttack();
}
void actRangeAttack(Warrior* o) {
if(weapon != NULL) {
o->life -= weapon->getRangeAttack();
int f = weapon->actRangeAttack();
if(f == 1) {
delete weapon;
weapon = NULL;
}
}
}
void move() {
move_count++;
if(move_count == 2) {
attack += 20;
life -= 9;
if(life <= 0)
life = 1;
move_count = 0;
}
}
};
class Lion: public Warrior {
public:
int loyalty;
Lion(int _n, int _life, int _loyalty): Warrior(_n, _life), loyalty(_loyalty) {
}
void show() {
printf("lion %d born\n", n);
printf("Its loyalty is %d\n", loyalty);
}
void showName() {
printf("lion %d", n);
}
void showWeapon() {
printf("no weapon");
}
int getAttack() {
return Info::ATK["lion"];
}
int getMeleeAttack() {
return getAttack();
}
int getBackAttack() {
return getAttack()/2;
}
int getFled() {
return loyalty <= 0;
}
};
class Wolf: public Warrior {
public:
Weapon *weapon[3];
Wolf(int _n, int _life): Warrior(_n, _life) {
weapon[0] = weapon[1] = weapon[2] = NULL;
}
void show() {
printf("wolf %d born\n", n);
}
void showName() {
printf("wolf %d", n);
}
void showWeapon() {
int f = 0;
for(int i = 0; i < 3; i++) {
if(weapon[i] != NULL) {
if(f) putchar(',');
weapon[i]->show(), f++;
}
}
if(f == 0)
printf("no weapon");
}
int getAttack() {
return Info::ATK["wolf"];
}
int getMeleeAttack() {
int m = 0;
if(weapon[2] != NULL)
m = weapon[2]->getMeleeAttack();
return getAttack() + m;
}
int getBackAttack() {
int m = 0;
if(weapon[2] != NULL)
m = weapon[2]->getMeleeAttack();
return getAttack()/2 + m;
}
void actMeleeAttack() {
if(weapon[2] != NULL) {
int f = weapon[2]->actMeleeAttack();
if(f == 0) {
delete weapon[2];
weapon[2] = NULL;
}
}
}
void actBackAttack() {
actMeleeAttack();
}
void actRangeAttack(Warrior* o) {
if(weapon[2] != NULL) {
o->life -= weapon[2]->getRangeAttack();
int f = weapon[2]->actRangeAttack();
if(f == 1)
weapon[2] = NULL;
}
}
};
class WarriorFactory {
public:
static Warrior* build(string kind, int n, float _morale, int _loyalty) {
if(!strcmp(kind.c_str(), "dragon"))
return new Dragon(n, Info::HP[kind], _morale);
else if(!strcmp(kind.c_str(), "ninja"))
return new Ninja(n, Info::HP[kind]);
else if(!strcmp(kind.c_str(), "iceman"))
return new Iceman(n, Info::HP[kind]);
else if(!strcmp(kind.c_str(), "lion"))
return new Lion(n, Info::HP[kind], _loyalty);
else
return new Wolf(n, Info::HP[kind]);
}
};
class Headquarter {
public:
int HP;
int dir;
int n;
Headquarter(int _HP, int _dir): HP(_HP), dir(_dir) {
n = 1;
}
void produce(vector<Warrior*> R[], vector<Warrior*> B[], int hh, int mm) {
string kind;
int born_cost;
if(dir == 1) { // RED
kind = Info::Rkind[n % 5];
} else { // BLUE
kind = Info::Bkind[n % 5];
}
born_cost = Info::HP[kind];
if(born_cost > HP)
return;
HP -= born_cost;
printf("%03d:%02d %s ", hh, mm, dir == 1 ? "red" : "blue");
Warrior *w = WarriorFactory::build(kind, n, (double) HP/ Info::HP[kind], HP);
w->show();
if(dir == 1) { // RED
R[0].push_back(w);
} else {
B[Info::N + 1].push_back(w);
}
n++;
}
};
void simulate() {
Headquarter RED(Info::M, 1), BLUE(Info::M, -1);
int timescale[] = {0, 5, 10, 20, 30, 35, 38, 40, 50, 55};
vector<Warrior*> R[Info::N + 2], B[Info::N + 2];
int cityHP[Info::N+2], cityFlag[Info::N+2], cityBattle[Info::N+2];
// cityFlag[], cityBattle[], NONE: 0, RED: 1, BLUE: 2
for(int i = 0; i <= Info::N + 1; i++)
cityHP[i] = cityFlag[i] = cityBattle[i] = 0;
for(int hour = 0; ; hour++) {
for(int i = 0; i < 10; i++) {
if(hour * 60 + timescale[i] > Info::T)
return;
int t = timescale[i];
if(t == 0) { // fixed
RED.produce(R, B, hour, t);
BLUE.produce(R, B, hour, t);
} else if(t == 5) { // fixed
for(int i = 0; i <= Info::N; i++) {
if(R[i].size() > 0) {
if(R[i][0]->getFled()) {
printf("%03d:%02d red ", hour, t);
R[i][0]->showName();
printf(" ran away\n");
R[i].clear();
}
}
}
for(int i = 1; i <= Info::N+1; i++) {
if(B[i].size() > 0) {
if(B[i][0]->getFled()) {
printf("%03d:%02d blue ", hour, t);
B[i][0]->showName();
printf(" ran away\n");
B[i].clear();
}
}
}
} else if(t == 10) { // fixed
for(int i = 0; i <= Info::N + 1; i++) {
if(R[i].size() > 0 && i <= Info::N) {
printf("%03d:%02d red ", hour, t);
R[i][0]->showName();
R[i][0]->move();
if(i + 1 < Info::N + 1)
printf(" marched to city %d with %d elements and force %d\n", i + 1, R[i][0]->life, R[i][0]->getAttack());
else
printf(" reached blue headquarter with %d elements and force %d\n", R[i][0]->life, R[i][0]->getAttack());
}
if(B[i].size() > 0 && i > 0) {
printf("%03d:%02d blue ", hour, t);
B[i][0]->showName();
B[i][0]->move();
if(i - 1 > 0)
printf(" marched to city %d with %d elements and force %d\n", i - 1, B[i][0]->life, B[i][0]->getAttack());
else
printf(" reached red headquarter with %d elements and force %d\n", B[i][0]->life, B[i][0]->getAttack());
}
}
for(int i = Info::N; i >= 0; i--) {
if(R[i].size() > 0) {
R[i+1].push_back(R[i][0]);
R[i].clear();
}
}
for(int i = 1; i <= Info::N + 1; i++) {
if(B[i].size() > 0) {
B[i-1].push_back(B[i][0]);
B[i].clear();
}
}
if(B[0].size() >= 2) {
printf("%03d:%02d red headquarter was taken\n", hour, t);
return ;
}
if(R[Info::N+1].size() >= 2) {
printf("%03d:%02d blue headquarter was taken\n", hour, t);
return ;
}
} else if(t == 20) { // fixed
for(int i = 1; i <= Info::N; i++)
cityHP[i] += 10;
} else if(t == 30) { // fixed
for(int i = 1; i <= Info::N; i++) {
if(R[i].size() == 1 && B[i].size() == 0) {
printf("%03d:%02d red ", hour, t);
R[i][0]->showName();
printf(" earned %d elements for his headquarter\n", cityHP[i]);
RED.HP += cityHP[i], cityHP[i] = 0;
}
if(R[i].size() == 0 && B[i].size() == 1) {
printf("%03d:%02d blue ", hour, t);
B[i][0]->showName();
printf(" earned %d elements for his headquarter\n", cityHP[i]);
BLUE.HP += cityHP[i], cityHP[i] = 0;
}
}
} else if(t == 35) { // fixed
for(int i = 0; i <= Info::N; i++) {
if(R[i].size() > 0 && B[i+1].size() > 0) {
R[i][0]->actRangeAttack(B[i+1][0]);
}
}
for(int i = 1; i <= Info::N + 1; i++) {
if(B[i].size() > 0 && R[i-1].size() > 0) {
B[i][0]->actRangeAttack(R[i-1][0]);
}
}
} else if(t == 38) { // fixed
for(int i = 0; i <= Info::N + 1; i++) {
if(R[i].size() > 0 && B[i].size() > 0) {
int rATK = R[i][0]->getMeleeAttack();
int bATK = B[i][0]->getMeleeAttack();
if(bATK >= R[i][0]->life) {
printf("%03d:%02d red ", hour, t);
R[i][0]->showName();
printf(" used a bomb and killed blue ");;
B[i][0]->showName();
puts("");
}
if(rATK >= B[i][0]->life) {
printf("%03d:%02d blue ", hour, t);
B[i][0]->showName();
printf(" used a bomb and killed red ");;
R[i][0]->showName();
puts("");
}
if(bATK >= R[i][0]->life || rATK >= B[i][0]->life) {
delete R[i][0];
R[i].clear();
delete B[i][0];
B[i].clear();
}
}
}
} else if(t == 40) {
int RB[Info::N+2];
for(int i = 1; i <= Info::N; i++) {
RB[i] = 0;
}
for(int i = 1; i <= Info::N; i++) {
if(R[i].size() > 0 && B[i].size() > 0) {
if(R[i][0]->life <= 0 || B[i][0]->life <= 0) {
} else {
if(cityFlag[i] == 1 || (cityFlag[i] == 0 && i%2 == 1)) {
int AT = R[i][0]->getMeleeAttack();
B[i][0]->life -= AT;
if(B[i][0]->life > 0) {
int BAT = B[i][0]->getBackAttack();
R[i][0]->life -= AT;
}
} else {
int AT = B[i][0]->getMeleeAttack();
R[i][0]->life -= AT;
if(R[i][0]->life > 0) {
int BAT = R[i][0]->getBackAttack();
B[i][0]->life -= AT;
}
}
}
if(R[i][0]->life > 0 && B[i][0]->life <= 0) {
RB[i] = 1;
if(cityBattle[i] == 1) {
cityFlag[i] = 1;
} else if(cityBattle[i] == 0) {
cityBattle[i] = 1;
}
}
if(B[i][0]->life > 0 && R[i][0]->life <= 0) {
RB[i] = 2;
if(cityBattle[i] == 2) {
cityFlag[i] = 2;
} else if(cityBattle[i] == 0) {
cityBattle[i] = 2;
}
}
}
if(R[i].size() > 0 && R[i][0]->life <= 0) {
delete R[i][0];
R[i].clear();
}
if(B[i].size() > 0 && B[i][0]->life <= 0) {
delete B[i][0];
B[i].clear();
}
}
for(int i = Info::N + 1; i >= 0; i--) {
if(RED.HP >= 8 && RB[i] == 1) {
RED.HP -= 8;
R[i][0]->life += 8;
}
}
for(int i = 0; i <= Info::N + 1; i++) {
if(BLUE.HP >= 8 && RB[i] == 2) {
BLUE.HP -= 8;
B[i][0]->life += 8;
}
}
for(int i = 0; i <= Info::N + 1; i++) {
if(RB[i] == 1) {
RED.HP += cityHP[i];
cityHP[i] = 0;
}
if(RB[i] == 2) {
BLUE.HP += cityHP[i];
cityHP[i] = 0;
}
}
} else if(t == 50) { // fixed
printf("%03d:%02d %d elements in red headquarter\n", hour, t, RED.HP);
printf("%03d:%02d %d elements in blue headquarter\n", hour, t, BLUE.HP);
} else if(t == 55) { // fixed
for(int i = 0; i <= Info::N + 1; i++) {
if(R[i].size() == 1) {
printf("%03d:%02d red ", hour, t);
R[i][0]->showName();
printf(" has ");
R[i][0]->showWeapon();
puts("");
}
if(B[i].size() == 1) {
printf("%03d:%02d blue ", hour, t);
B[i][0]->showName();
printf(" has ");
B[i][0]->showWeapon();
puts("");
}
}
}
}
}
}
int main() {
freopen("in.txt", "r+t", stdin);
freopen("out-my.txt", "w+t", stdout);
int testcase, cases = 0;
scanf("%d", &testcase);
while(testcase--) {
scanf("%d %d %d %d %d", &Info::M, &Info::N, &Info::R, &Info::K, &Info::T);
for(int i = 0; i < 5; i++)
scanf("%d", &Info::HP[Info::Mkind[i]]);
for(int i = 0; i < 5; i++)
scanf("%d", &Info::ATK[Info::Mkind[i]]);
printf("Case %d:\n", ++cases);
simulate();
}
return 0;
}
Read More +