csu_1508_地图的四着色

来源:互联网 发布:win7动态壁纸软件 编辑:程序博客网 时间:2024/05/18 23:11
#include<bits/stdc++.h> using namespace std;  #define min(a,b) ((a)<(b)?(a):(b))  #define max(a,b) ((a)>(b)?(a):(b))  #define memo(a,v) memset(a,v,sizeof(a))  #define pb push_back  #define all(a) a.begin(),a.end()  #define eps (1e-9)  #define inf (1<<25)  #define i64 long long  #define u64 unsigned i64  #define MOD 1000000007   char a[22][22];  int num[22][22];//标识国家,num[i][j]=1表示坐标i,j所在国家的编号为1  int mov[4][2] = {0,-1,-1,0,0,1,1,0},col[32],mask,n,m, k, ans, p;  bool mat[32][32]; //标识那几个国家相连  void renumber(int x,int y,char ch,int cnt){     //找连通图   num[x][y] = cnt;         int i,nx,ny;     for(i = 0;i<4;i++){         nx = x + mov[i][0];         ny = y + mov[i][1];         if(nx<0 || ny<0 || nx>=n || ny>=m || num[nx][ny] != -1 || a[nx][ny]!=ch) continue;         renumber(nx,ny,ch,cnt);     } }  int dfs(int u,int c,int flag){     if(col[u]!=-1){         if(col[u] != c) return 0;         return 1;     }     p++;     col[u] = c;     for(int v = 0;v<k;v++){         if(!mat[u][v] || ((mask & (1<<v))!=0) != flag ) //判断这个国家是不是他涂的 continue;         if(!dfs(v,1-c,flag))   //因为一个人只能涂两种颜色,所以c只有0,1两个值          return 0;     }     return 1; } void recurse(int pos,int cnt){     if(cnt>5) return;     if(pos == k){         if(cnt >= 2 && cnt<=k - 2){             int cur1 = 1, cur2 = 1;             memset(col,-1,sizeof(col));             int flag1 = 0, flag2 = 0;             for(int i = 0;i<k;i++){                 if(col[i]!=-1) continue;                 p = 0;   //涂了多少国家              if(mask & (1<<i)){   //是女朋友涂的                  if(!dfs(i,0,1)){     //判断编号为i的国家能有几种涂法,为0表示0种,1表示两种                   cur1 = 0;                         break;                     }                     cur1 *= 2;                     if(p>1)                         flag1 = 1;                     continue;                 }        //是男的涂的          if(!dfs(i,0,0)){                    cur2 = 0;                     break;                 }                 if(p>1)                     flag2 = 1;                 cur2 *= 2;             }             if(!flag1)  //如果flag1=0说明他没有涂一个国家,但根据dfs函数cur1会加2               cur1-=2;             if(!flag2)                 cur2-=2;             cur1 = max(0,cur1);             cur2 = max(0,cur2);             ans += cur1*cur2;         //    printf("%d %dn",mask,cur1*cur2);         }         return;     }     //这两个recurse()递归,有点像二叉树前序遍历,一个点不是你涂就是他涂 mask |= (1<<pos);     recurse(pos+1,cnt+1);     mask ^= (1<<pos);    //把mask的值还原到做'|'操作前的值 recurse(pos+1,cnt);   } int main(){     int i,j,x,y,l,cs = 1;     while(scanf("%d %d",&n,&m) == 2){         for(i = 0;i<n;i++)             scanf("%s",a[i]);         memset(num,-1,sizeof(num));         k = 0;//找连通图         for(i = 0;i<n;i++){             for(j = 0;j<m;j++){                 if(num[i][j]!=-1) continue;                 renumber(i,j,a[i][j],k++);             }         }         memset(mat,0,sizeof(mat));      //遍历哪些国家相邻   for(i = 0;i<n;i++){             for(j = 0;j<m;j++){                 for(l = 0;l<4;l++){                     x = i + mov[l][0];                     y = j + mov[l][1];                     if(x<0 || x>=n || y<0 || y>=m || num[i][j] == num[x][y]) continue;                     mat[num[i][j]][num[x][y]] = 1;                 }             }         }         ans = 0;         mask = 0;         recurse(0,0);         printf("Case %d: %dn",cs++, ans);     } return 0; } 

0 0
原创粉丝点击