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
", cas++, ans * 4);
92     }
93     return 0;
94 }
原文地址:https://www.cnblogs.com/fightfordream/p/6291195.html