ZOJ 3313-3321 The 10th Zhejiang University Programming Contest 部分题目解题报告

http://acm.zju.edu.cn/onlinejudge/showProblems.do?contestId=1&pageNumber=24

ZOJ 3313 Clock

题意:给一个角度,问每天时针和分针夹角不超过它的时间有多少秒

分析:假设时针不动,则分针和它夹角为x以内的比例为2x/360,再乘以一天的总秒数,发现答案就是480x。

 

 1 #include<stdio.h>
 2 
 3 int n, T;
 4 int main()
 5 {
 6     scanf("%d", &T);
 7     while(T--)
 8     {
 9         scanf("%d", &n);
10         printf("%.2f\n", 480.0 * n);
11     }
12     return 0;
13 }
View Code

 

 

ZOJ 3314 CAPTCHA

题意:给26个字母的7*16的矩阵,可以旋转180度,再给你一个大的矩阵图,识别里面的字母(完全相同的,不像HDU五周年赛有道题还有相似度)。大矩阵图保证每个联通块是一个合法字母,且合法字母不会相邻(联通)

分析:把给定字母都floodfill,得到一个更小的矩阵图,把大矩阵图的每个联通块一样处理,然后比照,这样不用考虑平移的问题。其实还有更暴力的做法,直接枚举大矩阵图左上角去和字母比照,然后有的字母像G会完全包含C,所以要特判G啥的。还有的做法干脆直接数每个字母有多少个‘M’,然后也能A= =。。代码很黄很暴力,慎重点开,比赛时写得快哭了= =。。虽然最后A了不过这题磨叽太多时间。

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<string>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 struct que{
  9     int x, y;
 10 } q[100000];
 11 string ch[60][10];
 12 string map[400];
 13 int vis[340][340];
 14 int n, m, ll, rr, uu, dd, cnt;
 15 int L[60], R[60], U[60], D[60];
 16 bool ans[60];
 17 bool vv[30][30];
 18 
 19 int dx[] = {-1, 1, 0, 0, -1, 1, -1, 1},
 20     dy[] = {0, 0, -1, 1, -1, -1, 1, 1};
 21 void floodfill(int x, int y, int &ll, int &rr, int &uu, int &dd)
 22 {
 23     uu = dd = x;
 24     ll = rr = y;
 25     vis[x][y] = cnt;
 26     int head, tail;
 27     head = tail = 0;
 28     q[head].x = x;
 29     q[head].y = y;
 30     tail ++;
 31     while (head < tail)
 32     {
 33         int xx = q[head].x, yy = q[head].y;
 34         head ++;
 35         for (int i = 0; i < 8; i++){
 36             int xt = xx + dx[i], yt = yy + dy[i];
 37             if (xt < 0 || yt < 0 || xt > n-1 || yt > m-1) continue;
 38             if (map[xt][yt] == 'M' && !vis[xt][yt]){
 39                 vis[xt][yt] = cnt;
 40                 ll = min(ll, yt);
 41                 rr = max(rr, yt);
 42                 uu = min(uu, xt);
 43                 dd = max(dd, xt);
 44                 q[tail].x = xt;
 45                 q[tail++].y = yt;
 46             }
 47         }
 48     }
 49 }
 50 void floodfill2(int x, int y, int &ll, int &rr, int &uu, int &dd, int pos)
 51 {
 52                 ll = min(ll, y);
 53                 rr = max(rr, y);
 54                 uu = min(uu, x);
 55                 dd = max(dd, x);
 56     int head, tail;
 57     head = tail = 0;
 58     q[head].x = x;
 59     q[head].y = y;
 60     tail ++;
 61     while (head < tail)
 62     {
 63         int xx = q[head].x, yy = q[head].y;
 64         vv[xx][yy] = true;
 65         head ++;
 66         for (int i = 0; i < 8; i++){
 67             int xt = xx + dx[i], yt = yy + dy[i];
 68             if (xt < 1 || yt < 0 || xt > 7 || yt > 15) continue;
 69             if (ch[pos][xt][yt] == 'M' && !vv[xt][yt]){
 70                 vv[xt][yt] = true;
 71                 ll = min(ll, yt);
 72                 rr = max(rr, yt);
 73                 uu = min(uu, xt);
 74                 dd = max(dd, xt);
 75                 q[tail].x = xt;
 76                 q[tail++].y = yt;
 77             }
 78         }
 79     }
 80 }
 81 
 82 bool check(int pos, int ll, int rr, int uu, int dd)
 83 {
 84     for (int i = uu; i <= dd; i++)
 85         for (int j = ll; j <= rr; j++){
 86             int xx = U[pos] + i - uu, yy = L[pos] + j - ll;
 87             if (map[i][j] == 'M' && vis[i][j] == cnt){
 88                 if (ch[pos][xx][yy] != 'M') return false;
 89             }
 90             if (ch[pos][xx][yy] == 'M' && vis[i][j] != cnt){
 91                 return false;
 92             }
 93         }
 94     return true;
 95 }
 96 int main()
 97 {
 98  ch[1][1] ="111111MMM1111111";  ch[2][1] = "1MMMMMMMMMMM1111";  ch[3][1] = "11111MMMMMMMM111";      
 99  ch[1][2] ="11111MM1MM111111";  ch[2][2] = "1MM11111111MM111";  ch[3][2] = "111MM1111111MM11";      
100  ch[1][3] ="1111MM111MM11111";  ch[2][3] = "1MM11111111MM111";  ch[3][3] = "11MM111111111MM1";      
101  ch[1][4] ="111MMMMMMMMM1111";  ch[2][4] = "1MMMMMMMMMMM1111";  ch[3][4] = "11MM111111111111";      
102  ch[1][5] ="11MM1111111MM111";  ch[2][5] = "1MM11111111MM111";  ch[3][5] = "11MM111111111MM1";      
103  ch[1][6] ="1MMM11111111MM11";  ch[2][6] = "1MM11111111MM111";  ch[3][6] = "111MM1111111MM11";      
104  ch[1][7] ="1MM1111111111MM1";  ch[2][7] = "1MMMMMMMMMMM1111";  ch[3][7] = "11111MMMMMMMM111";      
105 
106   ch[4][1] ="1MMMMMMMMMMM1111";  ch[5][1] ="1MMMMMMMMMMMM111"; ch[6][1] ="1MMMMMMMMMMMMM11";    
107   ch[4][2] ="1MM111111111MM11";  ch[5][2] ="1MM1111111111111"; ch[6][2] ="1MM1111111111111";
108   ch[4][3] ="1MM1111111111MM1";  ch[5][3] ="1MM1111111111111"; ch[6][3] ="1MM1111111111111";
109   ch[4][4] ="1MM1111111111MM1";  ch[5][4] ="1MMMMMMMMMMMM111"; ch[6][4] ="1MMMMMMMMMMMMM11";
110   ch[4][5] ="1MM1111111111MM1";  ch[5][5] ="1MM1111111111111"; ch[6][5] ="1MM1111111111111";
111   ch[4][6] ="1MM111111111MM11";  ch[5][6] ="1MM1111111111111"; ch[6][6] ="1MM1111111111111";
112   ch[4][7] ="1MMMMMMMMMMM1111";  ch[5][7] ="1MMMMMMMMMMMM111"; ch[6][7] ="1MM1111111111111";
113 
114   ch[7][1] ="11111MMMMMMMM111";   ch[8][1] ="1MM111111111MM11";   ch[9][1] ="11111MMMMMM11111";      
115   ch[7][2] ="111MM1111111MM11";   ch[8][2] ="1MM111111111MM11";   ch[9][2] ="1111111MM1111111";      
116   ch[7][3] ="11MM111111111MM1";   ch[8][3] ="1MM111111111MM11";   ch[9][3] ="1111111MM1111111";      
117   ch[7][4] ="11MM111111111111";   ch[8][4] ="1MMMMMMMMMMMMM11";   ch[9][4] ="1111111MM1111111";      
118   ch[7][5] ="11MM111111MMMMM1";   ch[8][5] ="1MM111111111MM11";   ch[9][5] ="1111111MM1111111";      
119   ch[7][6] ="111MM1111111MM11";   ch[8][6] ="1MM111111111MM11";   ch[9][6] ="1111111MM1111111";      
120   ch[7][7] ="11111MMMMMMMMM11";   ch[8][7] ="1MM111111111MM11";   ch[9][7] ="11111MMMMMM11111";      
121 
122   ch[10][1] ="1111MMMMMMMM1111";   ch[11][1] ="11MM111111MMM111";   ch[12][1] ="11MM111111111111";
123   ch[10][2] ="1111111MM1111111";   ch[11][2] ="11MM11111MMM1111";   ch[12][2] ="11MM111111111111";
124   ch[10][3] ="1111111MM1111111";   ch[11][3] ="11MM111MMM111111";   ch[12][3] ="11MM111111111111";
125   ch[10][4] ="1111111MM1111111";   ch[11][4] ="11MMMMM111111111";   ch[12][4] ="11MM111111111111";
126   ch[10][5] ="111MM11MM1111111";   ch[11][5] ="11MM111MMM111111";   ch[12][5] ="11MM111111111111";
127   ch[10][6] ="111MMM1MM1111111";   ch[11][6] ="11MM11111MMM1111";   ch[12][6] ="11MM111111111111";
128   ch[10][7] ="11111MMMM1111111";   ch[11][7] ="11MM111111MMMM11";   ch[12][7] ="11MMMMMMMMMMMM11";
129 
130   ch[13][1] ="1MM1111111111MM1";   ch[14][1] ="1MMM111111111MM1";   ch[15][1] ="11111MMMMMM11111";     
131   ch[13][2] ="1MMMM111111MMMM1";   ch[14][2] ="1MMMM11111111MM1";   ch[15][2] ="111MMM1111MMM111";     
132   ch[13][3] ="1MM1MM1111MM1MM1";   ch[14][3] ="1MM1MM1111111MM1";   ch[15][3] ="11MMM111111MMM11";     
133   ch[13][4] ="1MM11MMMMM111MM1";   ch[14][4] ="1MM11MM111111MM1";   ch[15][4] ="1MM1111111111MM1";     
134   ch[13][5] ="1MM1111M11111MM1";   ch[14][5] ="1MM1111MM1111MM1";   ch[15][5] ="11MMM111111MMM11";     
135   ch[13][6] ="1MM1111111111MM1";   ch[14][6] ="1MM111111MMM1MM1";   ch[15][6] ="111MMM1111MMM111";     
136   ch[13][7] ="1MM1111111111MM1";   ch[14][7] ="1MM11111111MMMM1";   ch[15][7] ="11111MMMMMM11111";     
137 
138  ch[16][1] ="1MMMMMMMMMMM1111";   ch[17][1] ="11111MMMMMM11111";   ch[18][1] ="1MMMMMMMMMMM1111";
139  ch[16][2] ="1MM111111111MM11";   ch[17][2] ="111MMM1111MMM111";   ch[18][2] ="1MM111111111MM11";
140  ch[16][3] ="1MM1111111111MM1";   ch[17][3] ="11MMM111111MMM11";   ch[18][3] ="1MM1111111111MM1";
141  ch[16][4] ="1MM111111111MM11";   ch[17][4] ="1MM1111111111MM1";   ch[18][4] ="1MM111111111MM11";
142  ch[16][5] ="1MMMMMMMMMMM1111";   ch[17][5] ="11MMM1MMMM1MMM11";   ch[18][5] ="1MMMMMMMMMMM1111";
143  ch[16][6] ="1MM1111111111111";   ch[17][6] ="111MMM11MMMMM111";   ch[18][6] ="1MM11111111MM111";
144  ch[16][7] ="1MM1111111111111";   ch[17][7] ="111111MMMM1MMMM1";   ch[18][7] ="1MM111111111MMM1";
145 
146 
147   ch[19][1] ="1111MMMMMMMM1111";   ch[20][1] ="11MMMMMMMMMMMM11";   ch[21][1] ="1MM1111111111MM1";     
148   ch[19][2] ="111MM1111111MM11";   ch[20][2] ="11MMMMMMMMMMMM11";   ch[21][2] ="1MM1111111111MM1";     
149   ch[19][3] ="11MMM1111111MMM1";   ch[20][3] ="1111111MM1111111";   ch[21][3] ="1MM1111111111MM1";     
150   ch[19][4] ="1111MMMMM1111111";   ch[20][4] ="1111111MM1111111";   ch[21][4] ="1MM1111111111MM1";     
151   ch[19][5] ="1MMM111MMMM11111";   ch[20][5] ="1111111MM1111111";   ch[21][5] ="1MMM11111111MMM1";     
152   ch[19][6] ="111MMM11111MMM11";   ch[20][6] ="1111111MM1111111";   ch[21][6] ="1MMM11111111MMM1";     
153   ch[19][7] ="11111MMMMMMM1111";   ch[20][7] ="1111111MM1111111";   ch[21][7] ="111MMMMMMMMMM111";     
154 
155 
156  ch[22][1] ="1MMMM111111MMMM1";   ch[23][1] ="1MM1111111111MM1";   ch[24][1] ="11MMM111111MMM11";
157  ch[22][2] ="11MMM111111MMM11";   ch[23][2] ="1MM1111111111MM1";   ch[24][2] ="111MMM1111MMM111";
158  ch[22][3] ="11MMM111111MMM11";   ch[23][3] ="11MM111MM111MM11";   ch[24][3] ="1111MMM11MMM1111";
159  ch[22][4] ="111MMM1111MMM111";   ch[23][4] ="11MM111MM111MM11";   ch[24][4] ="111111MMMM111111";
160  ch[22][5] ="1111MMM11MMM1111";   ch[23][5] ="11MM111MM111MM11";   ch[24][5] ="1111MMM11MMM1111";
161  ch[22][6] ="11111MM11MM11111";   ch[23][6] ="11MM1MM11MM1MM11";   ch[24][6] ="111MMM1111MMM111";
162  ch[22][7] ="111111MMMM111111";   ch[23][7] ="111MMM1111MMM111";   ch[24][7] ="11MMM111111MMM11";
163 
164 
165   ch[25][1] ="11MMM111111MMM11";   ch[26][1] ="111MMMMMMMMMM111";   
166   ch[25][2] ="111MMM1111MMM111";   ch[26][2] ="1111111111MM1111";   
167   ch[25][3] ="1111MMM11MMM1111";   ch[26][3] ="111111111MM11111";   
168   ch[25][4] ="111111MMMM111111";   ch[26][4] ="11111111MM111111";   
169   ch[25][5] ="1111111MM1111111";   ch[26][5] ="111111MM11111111";   
170   ch[25][6] ="1111111MM1111111";   ch[26][6] ="11111MM111111111";   
171   ch[25][7] ="1111111MM1111111";   ch[26][7] ="111MMMMMMMMMMM11";
172 
173     string tmp;
174     char xx;
175     for (int i = 1; i <= 26; i++){
176             for (int j = 1; j <= 7; j++){
177                 tmp = ch[i][j];
178                 for (int k = 0, l = tmp.length()-1; k < l; k++, l--){
179                     xx = tmp[k]; tmp[k] = tmp[l]; tmp[l] = xx;
180                 }
181                 ch[i+26][8-j] = tmp;
182             }
183     }
184     for (int i = 1; i <= 52; i++){
185         ll = 300, rr = 0, uu = 300, dd = 0;
186         memset(vv, 0, sizeof(vv));
187         for (int ii = 1; ii <= 7; ii++)
188             for (int jj = 0; jj < 16; jj++){
189                 if (ch[i][ii][jj] == 'M'){
190                     floodfill2(ii, jj, ll, rr, uu, dd, i);
191                     break;
192                 }
193             }
194 
195         L[i] = ll;
196         R[i] = rr;
197         U[i] = uu;
198         D[i] = dd;
199     }
200     /*
201     for (int i = U[25]; i <= D[25]; i++){
202         for (int j = L[25]; j <= R[25]; j++)
203             printf("%c", ch[25][i][j]);
204         printf("\n");
205     }
206     for (int i = U[25+26]; i <= D[25+26]; i++){
207         for (int j = L[25+26]; j <= R[25+26]; j++)
208             printf("%c", ch[25+26][i][j]);
209         printf("\n");
210     }
211     */
212     /*
213     for (int i = 26+6; i <= 26 + 6; i++){
214             for (int j = 1; j <= 7; j++){
215                 for (int k = 0; k < 16; k ++)
216                     cout << ch[i][j][k];
217                 cout << endl;
218             }
219             cout << endl;
220     }
221     */
222     while(scanf("%d%d", &n, &m)!= EOF)
223     {
224         for (int i = 0; i < n; i++) cin >> map[i];
225         memset(vis, 0, sizeof(vis));
226         memset(ans, 0, sizeof(ans));
227         cnt = 1;
228         for (int i = 0; i < n; i++)
229             for (int j = 0; j < m; j++){
230                 if (map[i][j] == 'M' && !vis[i][j]){
231                     floodfill(i, j, ll, rr, uu, dd);
232                 /*    
233                     for (int ii = uu; ii <= dd; ii++){
234                         for (int jj = ll; jj <= rr; jj++)
235                             printf("%c", map[ii][jj]);
236                         printf("\n");
237                     }
238                 */
239 
240                     for (int k = 1; k <= 52; k++){
241                         if (check(k, ll, rr, uu, dd)){
242                             ans[k] = true;
243                             break;
244                         }
245                     }
246                     cnt ++;
247                 }
248             }
249         for (int i = 1; i <= 26; i++)
250             if (ans[i] || ans[i+26]) printf("%c", i+'A'-1);
251         printf("\n");
252     }
253     return 0;
254 }
慎点

 

 

ZOJ 3315 Runaway Robot

题意:给一个m*n矩阵,有的格子不能走,只能向下或者向右,并且走法指令是循环的,比如是Down-Right,那么就是一直重复向下向右的过程。问要从(0,0)走到(m-1,n-1),所需要的最短指令长度。

分析:写完以后看了看别人的代码,发现写得不太好。做法就是递增枚举指令长度,再枚举向右长度,这样就可以确定一次指令会走的一个矩形,然后从矩形右下角开始又可以框出一个矩形,一直框到终点(如果最后矩形已经跑出地图却还没有框住终点这种指令就不可行),把这些矩形叠加起来取个交集(不能走的点做好标记,和下面3318一个思路),同时标记终点在矩形中的位置,然后判断能否从(0,0)走到终点在该矩形中的位置,以及终点在该矩形中的位置能不能走到矩形右下角,可行就是最优解了。

然后代码虽然跑得挺快,但是比较水。。一个是枚举的顺序不太好,我枚举的是向下的长度和向右的长度的二重循环,这样最优解不会是第一个解,然后判断的过程写的bfs。。其实只要两重循环递推一下就可以了。。啊。。反正过了就不检讨了。。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 struct que{
 7     int x, y;
 8 } q[30000];
 9 int n, m;
10 int dx[] = {0, 1},
11     dy[] = {1, 0};
12 char str[110][110];
13 bool vis[110][110], map[110][110];
14 bool bfs(int sx, int sy, int ex, int ey)
15 {
16     if (sx == ex && sy == ey) return 1;
17     int head, tail;
18     head = tail = 0;
19     q[tail].x = sx;
20     q[tail++].y = sy;
21     memset(vis, 0, sizeof(vis));
22     vis[sx][sy] = true;
23     while (head < tail)
24     {
25         int x = q[head].x, y = q[head++].y;
26         for (int i = 0; i < 2; i++){
27             int xx = x + dx[i], yy = y + dy[i];
28             if (xx > ex || yy > ey) continue;
29             if (vis[xx][yy] || !map[xx][yy]) continue;
30             vis[xx][yy] = 1;
31             if (xx == ex && yy == ey) return true;
32             q[tail].x = xx;
33             q[tail++].y = yy;
34         }
35     }
36     return false;
37 }
38 int main()
39 {
40     while(scanf("%d %d", &m, &n) != EOF)
41     {
42         for (int i = 0; i < n; i++) scanf("%s", str[i]);
43         memset(map, 1, sizeof(map));
44         for (int i = 0; i < n; i++)
45             for (int j = 0; j < m; j++)
46                 if (str[i][j] == 'X') map[i][j] = 0;
47         int ans = -1;
48         if (!bfs(0, 0, n-1, m-1)){
49             printf("%d\n", ans);
50             continue;
51         }
52         ans = n+m-2;
53         for (int i = 0; i <= n-1; i++){
54             for (int j = 0; j <= m-1; j++){
55                 if (i == 0 && j == 0) continue;
56                 if (ans <= i+j) break;
57                 memset(map, 1, sizeof(map));
58                 int nx = 0, ny = 0, ex = -1, ey = -1;
59                 while(nx < n && ny < m) nx += i, ny += j;
60                 if (nx < n-1 || ny < m-1) continue;
61                 nx = ny = 0;
62                 while(nx < n && ny < m){
63                     for (int k = nx; k <= nx + i; k ++)
64                         for (int l = ny; l <= ny + j; l++)
65                             if (k < n && l < m && str[k][l] == 'X') map[k-nx][l-ny] = 0;
66                     if (n-1 <= nx+i && m-1 <= ny+j){
67                         ex = n-1 - nx;
68                         ey = m-1 - ny;
69                         if (!map[0][0] || !map[ex][ey] || !map[i][j]) { ex = -1; break;}
70                     }
71                     nx += i; ny += j;
72                 }
73                 if (ex == -1) continue;
74                 if (bfs(0, 0, ex, ey) && bfs(ex, ey, i, j)) ans = i+j;
75             }
76         }
77         printf("%d\n", ans);
78     }    
79     return 0;
80 }
View Code

 

ZOJ 3316 Game

题意:19*19棋盘上有n个石子,两人轮流取,每次取一个,第一个人可以随意取,接下来都必须满足所取石子的位置与前一个人最后一次所取石子的位置的曼哈顿距离不超过给定距离L。取不了石子的人输,问后手有没有必胜策略。

分析:看似博弈,其实是图论,一般图最大匹配。目前还没有补。。

 

ZOJ 3317 Murder in Restaurant

题意:反正就是模拟题。。

分析:反正就是模拟题。。一边吃早餐一边补的,一不小心多排了一次序。。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 struct node{
 7     int b, e, id;
 8 } a[110];
 9 int ans[110], l[110];
10 int n, m;
11 bool cmp(node x, node y)
12 {
13     return x.b < y.b;
14 }
15 bool cmp1(node x, node y)
16 {
17     return x.id < y.id;
18 }
19 int main()
20 {
21     while(scanf("%d %d", &n, &m) && n+m)
22     {
23         for (int i = 0; i < n; i++){
24             scanf("%d %d", &a[i].b, &a[i].e);
25             a[i].id = i;
26         }
27         sort(a, a+n, cmp);
28         memset(l, 0, sizeof(l));
29         for (int i = 0; i < n; i++){
30             int j;
31             for (j = 1; j <= m; j++) if (l[j] <= a[i].b) break;
32             if (j > m) ans[a[i].id] = 0;
33             else{
34                 ans[a[i].id] = j;
35                 l[j] = a[i].e;
36             }
37 
38         }
39         sort(a, a+n, cmp1);
40         for (int i = 0; i < n; i++)
41             printf("%d\n", ans[i]);
42     }
43     return 0;
44 }
View Code

 

 

ZOJ 3318 Strange Country

题意:n个点,m张无向地图,边权都是1,给定起点s终点t,求一个最小cost,cost定义为每个图选定的s-t路的长度的和,然后下标相邻的图(i和i+1图)如果s-t路不同,还要再加上改变的费用1。

分析:dp[i]表示前i张图的最小cost,那么dp[i] = min(dp[j-1] + 1 + len[j][i] * (i - j + 1)),大概是这么个意思。len[j][i]表示,第j张图到第i张图的交集的最短路长度。复杂度是o(n^4),感觉是正解=。= 还有做法是每张图记下最短路和次短路,然后怎么怎么做的。。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int T, n, m, s, t, oo;
 7 int d[40], q[40], dp[40];
 8 int len[40][40];
 9 bool map[40][40][40], e[40][40];
10 int bfs()
11 {
12     memset(d, 127, sizeof(d));
13     oo = d[0];
14     d[s] = 0;
15     int head, tail;
16     head = tail = 0;
17     q[tail++] = s;
18     while(head < tail)
19     {
20         int u = q[head++];
21         for (int v = 1; v <= n; v++) if (e[u][v] && d[v] > d[u] + 1){
22             d[v] = d[u] + 1;
23             q[tail++] = v;
24         }
25     }
26     return d[t];
27 }
28 int main()
29 {
30     scanf("%d", &T);
31     while(T--)
32     {
33         scanf("%d %d %d %d", &n, &m, &s, &t);
34         memset(map, 0, sizeof(map));
35         int r, x, y;
36         for (int i = 0; i < m; i++){
37             scanf("%d", &r);
38             for (int j = 0; j < r; j++){
39                 scanf("%d %d", &x, &y);
40                 map[i][x][y] = true;
41                 map[i][y][x] = true;
42             }
43         }
44         for (int i = 0; i < m; i++){
45             memset(e, 1, sizeof(e));
46             for (int j = i; j < m; j++){
47                 for (int k = 1; k <= n; k++)
48                     for (int l = 1; l <= n; l++)
49                         e[k][l] &= map[j][k][l];
50                 len[i][j] = bfs();
51             }
52         }
53         dp[0] = len[0][0];
54         for (int i = 1; i < m; i++){
55             if (len[0][i] != oo) dp[i] = len[0][i] * (i+1);
56             else dp[i] = oo;
57             for (int j = 0; j < i; j++){
58                 if (len[j+1][i] != oo)
59                     dp[i] = min(dp[i], dp[j] + (i-j) * len[j+1][i] + 1);
60             }
61         }
62         printf("%d\n", dp[m-1]);
63     }
64     return 0;
65 }
View Code

 

 

ZOJ 3319 Islands

题意:给一个有向图,现在让你加边,使得最后的图每个点都在环内,而且除了环没有多余的边,问方案数。

分析:看似图论,其实是组合数学。首先判断不满足要求的图,剩下的图肯定是只有链和孤立点,然后我还不会。。队友A掉了,用的错排公式还有组合数还有DP。有空补吧=。=

update:今天写了,剩下的链数是numofchain,剩下点数numofpt,链是可以自己组成环的,而点必须和链和点互相结合组成。所以枚举和点一起组成环的链的个数,这里是一个组合数c(i, numofchain),选出来的链和点实际上等价了,即一共i+numofpt个点,考虑它们组成环的方法数。编号为i的点不能连到i,而连其他编号的点都是可以的,这启发我们实际上这个方法数就是错位排序数。任意一种错位排列和对应编号一一连线,就是一种组成环的方法。网上看到还有递推出来的,大家可以搜一搜。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 const int mo = 10000007;
 6 char str[110];
 7 int n, numofpt, numofchain, tot;
 8 bool flag;
 9 int in[110], ch[110];
10 long long c[110][110], d[110];
11 void init()
12 {
13     memset(c, 0, sizeof(c));
14     c[0][0] = 1;
15     for (int i = 1; i <= 100; i++)
16         for (int j = 0; j <= i; j++)
17             if (i == j || j == 0) c[i][j] = 1;
18             else c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mo;
19     d[0] = 1;
20     d[1] = 0;
21     for (int i = 2; i <= 100; i++)
22         d[i] = (d[i-1] + d[i-2]) * (i-1) % mo;
23 }
24 void read()
25 {
26     memset(in, 0, sizeof(in));
27     memset(ch, 0, sizeof(ch));
28     for (int i = 0; i < n; i++){
29         scanf("%s", str);
30         for (int j = 0; j < n; j++)
31             if (str[j] == 'Y') ch[i]++, in[j]++;
32     }
33     numofpt = tot = numofchain = 0;
34     flag = false;
35     for (int i = 0; i < n; i++){
36         if (in[i] > 1 || ch[i] > 1){
37             flag = true;
38             break;
39         }
40         if (in[i] == 0){
41             tot ++;
42             if (ch[i] == 0) numofpt ++;
43         }
44     }
45     numofchain = tot - numofpt;
46 }
47 void solve()
48 {        
49     if (flag){
50         puts("0");
51         return;
52     }
53     else{
54         long long ans = 0;
55         for (int i = 0; i <= numofchain; i++){
56             ans = (ans + c[numofchain][i] * d[i + numofpt]) % mo;
57         }
58         printf("%lld\n", ans);
59     }
60 }
61 int main()
62 {
63     init();
64     while(scanf("%d", &n) && n)
65     {
66         read();
67         solve();
68     }
69     return 0;
70 }
View Code

 

 

 

 

ZOJ 3320 Break Out

题意:打砖块。n×m的格子,每个砖块有价值,有的还有奖励。奖励很坑爹,打了有奖励的砖块你就会去捡奖励,从而丢球掉一个生命值。每次可以任意选一列最下面的砖块打,打通一列后可以从上面打,给你L的生命值,问你最多能得多少价值。

分析:只A了20个人。。而且没搜到题解。。想了一个状态和转移方程,不过复杂度很高,有空看看能不能优化优化试着A了?=。=

 

ZOJ 3321 Circle

题意:给你无向图,判断是不是刚好是一个环。

分析:数据范围奇小,以至于以为自己读错题,其实就是那么简单。。我写了个dfs,其实也可以判断点的度数是不是都为2,边数是否等于点数,以及floyd,选一个点看看是不是和任意点可达。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<set>
 8 #include<map>
 9 #include<queue>
10 #include<ctime>
11 #include<string>
12 using namespace std;
13 
14 int n, m, x, y;
15 bool e[30][30];
16 bool vis[30];
17 bool dfs(int x, int dep)
18 {
19     for (int i = 1; i <= n; i++)
20         if (e[x][i] && !vis[i]){
21             vis[i] = true;
22             return dfs(i, dep+1);
23         }
24         else if (e[x][i] && i == 1 && dep == n) return true;
25     return false;
26 }
27 int main()
28 {
29     while(scanf("%d %d", &n, &m) != EOF)
30     {
31         memset(e, 0, sizeof(e));
32         for (int i = 0; i < m; i++){
33             scanf("%d %d", &x, &y);
34             e[x][y] = true;
35             e[y][x] = true;
36         }
37         if (n != m){
38             printf("NO\n");
39             continue;
40         }
41         if (n < 3){
42             printf("NO\n");
43             continue;
44         }
45         memset(vis, 0, sizeof(vis));
46         vis[1] = true;
47         if (dfs(1, 1))
48             printf("YES\n");
49         else printf("NO\n");
50     }
51     return 0;
52 }
View Code

 

posted @ 2014-08-10 16:46  james47  阅读(484)  评论(0编辑  收藏  举报