CSU_1508_地图的四着色

来源:互联网 发布:mac速度慢怎么办 编辑:程序博客网 时间:2024/05/24 16:17

 地图的四着色

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 66  Solved: 35
[Submit][Status][Web Board]

Description

有一个R行C列的网格地图,每个国家是一个四连通区域。你的任务是用红,绿,蓝,黄四种颜色给地图着色,使得相邻国家的颜色不同。
一个人着色比较无趣,所以你想请女朋友陪你一起涂——你涂红绿,她涂蓝黄。当然,绅士是不会让让女朋友受累的,所以她最多只需涂5个国家(恰好5个也行)。
你的任务是统计有多少种着色的方法。注意,每个颜色都至少要用一次。

Input

输入包含不超过100组数据。每组数据第一行为两个整数R和C (1<=R,C<=20),即网格的行数和列数。以下R行每行C个大写字母。相同字母所组成的四连通区域代表一个国家。输入保证国家数目不超过30,并且大多数测试点的国家数都比较小。

Output

对于每组数据,输出测试点编号和着色方案数。

Sample Input

2 4AABBBBAA1 5ABABA4 7AABAABBABBCCCBBBAACBBCCABBAC

Sample Output

Case 1: 24Case 2: 144Case 3: 3776

HINT


首先建图,注意如果直接用邻接表的话要判重

所以先用邻接矩阵,然后再转成邻接表(因为显然是稀疏图)

之后dfs给地图上色就好了

这里注意这个问题容易超时

然后其实对于第一个国家的涂色可以只分男人和女人涂,然后把结果乘二就可以了


#include <iostream>//#include<bits/stdc++.h>#include <stdio.h>#include <string.h>#include <queue>using namespace std; const int MT=22;char ti[MT][MT];int ti2[MT][MT];   //转化成一个国家对应一个数字 const int M=32;int g[M][M];       //邻接矩阵int gg[M][M];      //邻接表int col[M];int isu[5]; queue<int > re; int ans; int dx[]={0,0,1,-1};int dy[]={1,-1,0,0}; void bfs(int stx,int sty,int na)    //转化成一个国家一个数字{    while(!re.empty())        re.pop();    ti2[stx][sty]=na;    re.push(stx+MT*sty);    while(!re.empty())    {        int t=re.front();        re.pop();        int tx=t%MT,ty=t/MT;        for(int i=0;i<4;i++)        {            int x=tx+dx[i],y=ty+dy[i];            if(!ti2[x][y]&&ti[stx][sty]==ti[x][y])            {                ti2[x][y]=na;                re.push(x+MT*y);            }        }    }} //void dfs_g(int stx,int sty,int na)//{//    ti2[stx][sty]=na;//    for(int i=0;i<4;i++)//    {//        int x=stx+dx[i],y=sty+dy[i];//        if(!ti2[x][y]&&ti[stx][sty]==ti[x][y])//        {//            ti2[x][y]=na;//            dfs_g(x,y,na);//        }//    }//} void dfs(int now,int na,int nn)       //涂色,now是现在涂第几个国家,na是一共有多少国家,nn女人涂了几个国家{    if(nn>5)        return;    if(now==na)    {         if(isu[1]+isu[2]+isu[3]+isu[4]==4)        {            ans++;//            for(int i=1;i<na;i++)//                cout<<col[i]<<" ";//            cout<<endl;        }        return;    }    for(int i=1;i<=4;i++)    {        if(i==3&&nn==5)       //这个剪枝非常重要,提前把这种不成立的情况去掉可以少太多的判断和搜索            return;        int f=1;        for(int j=1;j<=gg[now][0];j++)        {            if(i==col[gg[now][j]])            {                f=0;                break;            }        }        if(f)        {            int chan=0;            if(i==1||i==2)            {                col[now]=i;                if(!isu[i])                {                    isu[i]=1;                    chan=i;                }                dfs(now+1,na,nn);                col[now]=0;                if(chan)                    isu[chan]=0;            }            else            {                col[now]=i;                if(!isu[i])                {                    isu[i]=1;                    chan=i;                }                dfs(now+1,na,nn+1);                col[now]=0;                if(chan)                    isu[chan]=0;            }        }    }} int main(){    int n,m;    //double cl = clock();    //freopen("f.in","r",stdin);    int ca=1;    while(scanf("%d%d",&n,&m)!=EOF)    {        ans=0;        int na=1;        memset(ti,0,sizeof(ti));        memset(ti2,0,sizeof(ti2));        memset(g,0,sizeof(g));        memset(gg,0,sizeof(gg));//        for(int i=1;i<M;i++)//            gg[i][0]=0;        for(int i=1;i<=n;i++)            scanf("%s",ti[i]+1);         for(int i=1;i<=n;i++)  //转化为1片一个数        for(int j=1;j<=m;j++)        {            if(!ti2[i][j])                bfs(i,j,na++);        }         for(int i=1;i<=n;i++)        for(int j=1;j<m;j++)        {            if(ti2[i][j]!=ti2[i][j+1])            {                int t1=ti2[i][j],t2=ti2[i][j+1];                g[t1][t2]=g[t2][t1]=1;            }        }        for(int i=1;i<n;i++)        for(int j=1;j<=m;j++)        {            if(ti2[i][j]!=ti2[i+1][j])            {                int t1=ti2[i][j],t2=ti2[i+1][j];                g[t1][t2]=g[t2][t1]=1;            }        }        for(int i=1;i<na;i++)   //矩阵转表        {             for(int j=1;j<i;j++)            {                if(g[i][j])                {                    gg[i][++gg[i][0]]=j;                    gg[j][++gg[j][0]]=i;                }            }        } //        for(int i=1;i<na;i++)//        {//            for(int j=1;j<=gg[i][0];j++)//            {//                cout<<i<<" "<<gg[i][j]<<endl;//            }//        }//        cout<<na<<endl;        //建图如上         col[1]=1;isu[1]=1;isu[2]=isu[3]=isu[4]=0;        dfs(2,na,0);        col[1]=3;isu[3]=1;isu[1]=isu[2]=isu[4]=0;        dfs(2,na,1);         printf("Case %d: %d\n",ca++,ans<<1);    }//    cl = clock() - cl;//    fprintf(stderr,"Run Time = %lf\n",cl/CLOCKS_PER_SEC);    return 0;} 


0 0
原创粉丝点击