CSU 1508:地图的四着色(DFS+剪枝)
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1508
题意:地图中四联通的块是一个国家,A和B每个人可以涂两种颜色,且B不能涂超过5次,相邻的国家不能涂一样的颜色,并且最后每种颜色都要用上,问共有多少种涂色方案。
思路:先DFS处理出图中的国家,然后先用一个邻接矩阵存下相邻的国家(直接用邻接表会有重边),然后再用邻接表存图。数方案个数的时候,假设共有a,b,c,d这四种颜色,A可以涂a,b,B可以涂c,d。因为颜色之间没有差异,所以A先涂a颜色,B先涂c颜色,那么和A先涂b颜色,B先涂c或者d颜色是一样的。所以暂时假设A先涂a颜色,B先涂c颜色,然后利用平时判断二分图一样,去染色,记得染完色之后col[num]要置0。通过约束条件得到答案后,因为有先涂a-c,a-d,b-c,b-d这四种情况,所以最后答案*4。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <string> 7 #include <iostream> 8 #include <stack> 9 #include <map> 10 #include <queue> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 #define N 40 15 #define INF 0x3f3f3f3f 16 struct node { 17 int v, nxt; 18 }edge[N*N*2]; 19 int n, m, vis[N][N], tu[N][N], cnt, col[N], head[N], ans, tot, dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1}; 20 char mp[N][N]; 21 22 bool check(int x, int y) { if(0 < x && x <= n && 0 < y && y <= m) return true; return false; } 23 24 void Add(int u, int v) { edge[tot].v = v; edge[tot].nxt = head[u]; head[u] = tot++; } 25 26 void DFS(int x, int y, char c) { 27 for(int i = 0; i < 4; i++) { 28 int nx = dx[i] + x, ny = dy[i] + y; 29 if(check(nx, ny) && !vis[nx][ny] && mp[nx][ny] == c) { 30 vis[nx][ny] = cnt; DFS(nx, ny, c); 31 } 32 } 33 } 34 35 bool judge(int u, int c) { 36 for(int i = head[u]; ~i; i = edge[i].nxt) 37 if(col[edge[i].v] == c) return false; 38 return true; 39 } 40 41 void dfs(int num, int a, int b, int c, int d) { 42 if(num == cnt + 1) { 43 if(a && b && c && d) ans++; 44 return ; 45 } 46 if(judge(num, 1)) { 47 col[num] = 1; 48 dfs(num + 1, a + 1, b, c, d); 49 col[num] = 0; 50 } 51 if(a > 0 && judge(num, 2)) { 52 col[num] = 2; 53 dfs(num + 1, a, b + 1, c, d); 54 col[num] = 0; 55 } 56 if(c + d < 5 && judge(num, 3)) { 57 col[num] = 3; 58 dfs(num + 1, a, b, c + 1, d); 59 col[num] = 0; 60 } 61 if(c + d < 5 && c && judge(num, 4)) { 62 col[num] = 4; 63 dfs(num + 1, a, b, c, d + 1); 64 col[num] = 0; 65 } 66 } 67 68 int main() 69 { 70 int cas = 1; 71 while(~scanf("%d%d", &n, &m)) { 72 for(int i = 1; i <= n; i++) scanf("%s", mp[i] + 1); 73 memset(head, -1, sizeof(head)); 74 memset(vis, 0, sizeof(vis)); 75 memset(col, 0, sizeof(col)); 76 memset(tu, 0, sizeof(tu)); 77 tot = cnt = ans = 0; 78 for(int i = 1; i <= n; i++) 79 for(int j = 1; j <= m; j++) 80 if(!vis[i][j]) { cnt++; vis[i][j] = cnt; DFS(i, j, mp[i][j]); } 81 for(int i = 1; i <= n; i++) { 82 for(int j = 1; j <= m; j++) { 83 if(vis[i-1][j] && vis[i-1][j] != vis[i][j]) tu[vis[i][j]][vis[i-1][j]] = tu[vis[i-1][j]][vis[i][j]] = 1; 84 if(vis[i][j-1] && vis[i][j-1] != vis[i][j]) tu[vis[i][j-1]][vis[i][j]] = tu[vis[i][j]][vis[i][j-1]] = 1; 85 } 86 } 87 for(int i = 1; i <= cnt; i++) 88 for(int j = 1; j <= cnt; j++) 89 if(i != j && tu[i][j]) Add(i, j); 90 dfs(1, 0, 0, 0, 0); 91 printf("Case %d: %d\n", cas++, ans * 4); 92 } 93 return 0; 94 }