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。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
ZOJ 3314 CAPTCHA
题意:给26个字母的7*16的矩阵,可以旋转180度,再给你一个大的矩阵图,识别里面的字母(完全相同的,不像HDU五周年赛有道题还有相似度)。大矩阵图保证每个联通块是一个合法字母,且合法字母不会相邻(联通)
分析:把给定字母都floodfill,得到一个更小的矩阵图,把大矩阵图的每个联通块一样处理,然后比照,这样不用考虑平移的问题。其实还有更暴力的做法,直接枚举大矩阵图左上角去和字母比照,然后有的字母像G会完全包含C,所以要特判G啥的。还有的做法干脆直接数每个字母有多少个‘M’,然后也能A= =。。代码很黄很暴力,慎重点开,比赛时写得快哭了= =。。虽然最后A了不过这题磨叽太多时间。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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。。其实只要两重循环递推一下就可以了。。啊。。反正过了就不检讨了。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
ZOJ 3316 Game
题意:19*19棋盘上有n个石子,两人轮流取,每次取一个,第一个人可以随意取,接下来都必须满足所取石子的位置与前一个人最后一次所取石子的位置的曼哈顿距离不超过给定距离L。取不了石子的人输,问后手有没有必胜策略。
分析:看似博弈,其实是图论,一般图最大匹配。目前还没有补。。
ZOJ 3317 Murder in Restaurant
题意:反正就是模拟题。。
分析:反正就是模拟题。。一边吃早餐一边补的,一不小心多排了一次序。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
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),感觉是正解=。= 还有做法是每张图记下最短路和次短路,然后怎么怎么做的。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
ZOJ 3319 Islands
题意:给一个有向图,现在让你加边,使得最后的图每个点都在环内,而且除了环没有多余的边,问方案数。
分析:看似图论,其实是组合数学。首先判断不满足要求的图,剩下的图肯定是只有链和孤立点,然后我还不会。。队友A掉了,用的错排公式还有组合数还有DP。有空补吧=。=
update:今天写了,剩下的链数是numofchain,剩下点数numofpt,链是可以自己组成环的,而点必须和链和点互相结合组成。所以枚举和点一起组成环的链的个数,这里是一个组合数c(i, numofchain),选出来的链和点实际上等价了,即一共i+numofpt个点,考虑它们组成环的方法数。编号为i的点不能连到i,而连其他编号的点都是可以的,这启发我们实际上这个方法数就是错位排序数。任意一种错位排列和对应编号一一连线,就是一种组成环的方法。网上看到还有递推出来的,大家可以搜一搜。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
ZOJ 3320 Break Out
题意:打砖块。n×m的格子,每个砖块有价值,有的还有奖励。奖励很坑爹,打了有奖励的砖块你就会去捡奖励,从而丢球掉一个生命值。每次可以任意选一列最下面的砖块打,打通一列后可以从上面打,给你L的生命值,问你最多能得多少价值。
分析:只A了20个人。。而且没搜到题解。。想了一个状态和转移方程,不过复杂度很高,有空看看能不能优化优化试着A了?=。=
ZOJ 3321 Circle
题意:给你无向图,判断是不是刚好是一个环。
分析:数据范围奇小,以至于以为自己读错题,其实就是那么简单。。我写了个dfs,其实也可以判断点的度数是不是都为2,边数是否等于点数,以及floyd,选一个点看看是不是和任意点可达。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }