• 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 }
  • 相关阅读:
    运算符
    java--有关前台展示图片流的用法
    TortoiseSVN--Subversion客户端使用详解及问题解决
    SVN 文件的解锁方法
    JDBC中获取数据表的信息
    tomcat配置文件解决乱码问题
    正则表达式常用匹配
    Java:如何选择最为合适的Web开发框架
    键盘enter事件 兼容FF和IE和Opera
    PayPal 支付接口详解
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6291195.html
Copyright © 2020-2023  润新知