这道题目主要是构图,之后就是水水地求连通分量个数了,用广搜,用深搜,用并查集都行,不过并查集效率要高。
/* *State: HDU1198 46MS 372K 2322 B C++ *题目大意: * 给定A~K个固定的小方块,方块中有水管,然后要求凑这些小方块成为 * 一个大矩形,求最后形成的连通分量数目。 *解题思路: * 主要是构图比较特别。枚举每个小方块构图,最后用dfs查连通分量数即可。 * 图可构为无向图。 *解题感想: * 好像用map慢了许多。第三次优化用了并查集,果然0ms了,连建图都省了 */
并查集版本:
View Code
//第三次优化 //State: HDU1198 0MS 264K 2185 B C++ //果然求无向图连通分量数,用并查集要快很多 #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 2505; typedef struct _node { int up, down, left, right; _node():up(0), down(0), left(0), right(0) {}; }N; typedef struct _Set { int parent; }Set; Set mySet[MAXN]; N sq[11]; char Map[51][51]; int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; void init() { for(int i = 0; i < MAXN; i++) mySet[i].parent = i; sq[0].up = sq[0].left = 1; sq[1].up = sq[1].right = 1; sq[2].left = sq[2].down = 1; sq[3].down = sq[3].right = 1; sq[4].up = sq[4].down = 1; sq[5].left = sq[5].right = 1; sq[6].left = sq[6].up = sq[6].right = 1; sq[7].left = sq[7].up = sq[7].down = 1; sq[8].left = sq[8].down = sq[8].right = 1; sq[9].up = sq[9].right = sq[9].down = 1; sq[10].left = sq[10].up = sq[10].right = sq[10].down = 1; } int findSet(int x) { if(x != mySet[x].parent) mySet[x].parent = findSet(mySet[x].parent); return mySet[x].parent; } void Union(int x, int y) { x = findSet(x); y = findSet(y); if(x == y) return ; else mySet[y].parent = x; } void bulid(int n, int m) { int ni, nj; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) { for(int k = 0; k < 4; k++) { ni = i + dir[k][0]; nj = j + dir[k][1]; if(ni >= 0 && ni < n && nj >= 0 && nj < m) { int u = i * m + j; int v = ni * m + nj; int ind = Map[i][j] - 'A'; int other = Map[ni][nj] - 'A'; if(sq[ind].up && sq[other].down && k == 0) Union(u, v); if(sq[ind].right && sq[other].left && k == 1) Union(u, v); if(sq[ind].down && sq[other].up && k == 2) Union(u, v); if(sq[ind].left && sq[other].right && k == 3) Union(u, v); } } } } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m; while(scanf("%d %d", &n, &m), n > 0 && m > 0) { init(); for(int i = 0; i < n; i++) scanf("%s", Map[i]); bulid(n, m); int tolN = n * m, ans = 0; for(int i = 0; i < tolN; i++) { if(mySet[i].parent == i) ans++; } printf("%d\n", ans); } return 0; }
深搜版本:
View Code
1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXN = 2505; 8 typedef struct _node 9 { 10 int up, down, left, right; 11 _node():up(0), down(0), left(0), right(0) {}; 12 }N; 13 14 N sq[11]; 15 char Map[51][51]; 16 vector<int> vec[MAXN]; 17 int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; 18 int vst[MAXN]; 19 20 void init() 21 { 22 memset(vst, 0, sizeof(vst)); 23 for(int i = 0; i < MAXN; i++) 24 vec[i].clear(); 25 26 sq[0].up = sq[0].left = 1; 27 sq[1].up = sq[1].right = 1; 28 sq[2].left = sq[2].down = 1; 29 sq[3].down = sq[3].right = 1; 30 sq[4].up = sq[4].down = 1; 31 sq[5].left = sq[5].right = 1; 32 sq[6].left = sq[6].up = sq[6].right = 1; 33 sq[7].left = sq[7].up = sq[7].down = 1; 34 sq[8].left = sq[8].down = sq[8].right = 1; 35 sq[9].up = sq[9].right = sq[9].down = 1; 36 sq[10].left = sq[10].up = sq[10].right = sq[10].down = 1; 37 } 38 39 void addEdge(int u, int v) 40 { 41 vec[u].push_back(v); 42 vec[v].push_back(u); 43 } 44 45 void bulid(int n, int m) 46 { 47 int ni, nj; 48 for(int i = 0; i < n; i++) 49 for(int j = 0; j < m; j++) 50 { 51 for(int k = 0; k < 4; k++) 52 { 53 ni = i + dir[k][0]; 54 nj = j + dir[k][1]; 55 if(ni >= 0 && ni < n && nj >= 0 && nj < m) 56 { 57 int u = i * m + j; 58 int v = ni * m + nj; 59 60 int ind = Map[i][j] - 'A'; 61 int other = Map[ni][nj] - 'A'; 62 63 if(sq[ind].up && sq[other].down && k == 0) 64 addEdge(u, v); 65 if(sq[ind].right && sq[other].left && k == 1) 66 addEdge(u, v); 67 if(sq[ind].down && sq[other].up && k == 2) 68 addEdge(u, v); 69 if(sq[ind].left && sq[other].right && k == 3) 70 addEdge(u, v); 71 } 72 } 73 } 74 } 75 76 void dfs(int n) 77 { 78 vst[n] = 1; 79 for(unsigned i = 0; i < vec[n].size(); i++) 80 { 81 int son = vec[n][i]; 82 if(!vst[son]) 83 { 84 dfs(son); 85 } 86 } 87 } 88 89 int main(void) 90 { 91 #ifndef ONLINE_JUDGE 92 freopen("in.txt", "r", stdin); 93 #endif 94 95 int n, m; 96 while(scanf("%d %d", &n, &m), n > 0 && m > 0) 97 { 98 init(); 99 100 for(int i = 0; i < n; i++) 101 scanf("%s", Map[i]); 102 bulid(n, m); 103 int tolN = n * m, ans = 0; 104 for(int i = 0; i < tolN; i++) 105 { 106 if(!vst[i]) 107 { 108 ans++; 109 dfs(i); 110 } 111 } 112 printf("%d\n", ans); 113 } 114 return 0; 115 }