Description
四色定理是给定的任何一个平面分离成连续的区域,产生一个包含许多区域的图,四种颜色给不同区域涂色,任意相邻的两个区域颜色不能相同。
-维基百科,自由的百科全书
在这个问题上,你必须解决四色问题。嘿,我只是在开玩笑。
你需要解决一个类似的问题:有一个包含从1到K一共K种颜色的N×M棋盘,使得任意两个相邻的区块不能有相同的颜色(如果它们的上、下、左、右任意一边的颜色与自身颜色不同)。第i种颜色可以被使用Ci次。
Input
第一行包含一个整数T(1<=T<= 5000), T表示测试用例的数量。
对每一个测试用例第一行包含三个整数N,M,K(0<N,M<=5,0<K<=N*M)。
第二行包含K个整数Ci(Ci>0),表示第i种颜色可以被使用的次数。
输入保证C1+ C2+...+ CK=N*M。
Output
对每个测试用例,第一行包含“Case #x:”, x是用例的序号( 从1开始)。
如果有满足条件的涂色方法就输出“YES”,如果没有就输出“NO”。接下来的N行每行由M个表示第i种颜色的数字构成,数字之间有一个空格隔开。
如果有多重涂法,输出其中的一种。
Sample Input
4 1 5 2 4 1 3 3 4 1 2 2 4 2 3 3 2 2 2 3 2 3 2 2 2
Sample Output
Case #1: NO Case #2: YES 4 3 4 2 1 2 4 3 4 Case #3: YES 1 2 3 2 3 1 Case #4: YES 1 2 2 3 3 1
其实题目并不难,只是有一个剪枝想不到,导致超时,这个题跟数独的题目基本上是一样的,这个关键的剪枝点就是格子中剩余的格子数(也就是没有涂色的格子数)必须大于剩余颜色中最多的那个乘2,比如,一个3x3的格子,同一种颜色最多可以放置9个
AC代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<stack> #include<queue> using namespace std; int t,n,m,k,flag; int maze[6][6]; int color[27]; int d[4][2]={{0,-1}, {-1,0}, {0,1}, {1,0}}; int check(int num, int clr)//检测第m个点,放上i种颜色是否符合要求 { int Max=0; for(int i=1;i<=k;i++)//核心剪枝代码 if(color[i]>Max) Max=color[i];//Max是剩余可用颜色中,数量最多的颜色的个数 if(Max*2>n*m-num+1)//如果不满足剪枝情况,直接return 0,继续探索下一个可用的颜色 return 0; if(color[clr]==0)//颜色用完了,该颜色就不能用了 return 0; int x,y;//根据是第几个格子,计算出该格子在图中的坐标 x=num/m;//行坐标 y=num%m;//列坐标 for(int i=0;i<4;i++) { int xx=x+d[i][0]; int yy=y+d[i][1]; if(xx<0 || x>=n || y<0 || y>=m) continue; if(maze[xx][yy]==clr)//如果出现了,周围有跟它颜色一样的,该颜色则不可用,return 0 return 0; } return 1; } void dfs(int nn) { int x,y; x=nn/m; y=nn%m; if(flag) return; if(nn >= n*m) { flag=1; return; } for(int i=1;i<=k;i++) { if(check(nn,i))//该颜色是否符合要求 { maze[x][y]=i; color[i]--; dfs(nn+1); if(flag) return; maze[x][y]=0; color[i]++; } } } int main() { scanf("%d",&t); int cnt=0,Max,MMax,MMin; while(t--) { Max=0; memset(maze,0,sizeof(maze)); flag=0; scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=k;i++) scanf("%d",&color[i]); printf("Case #%d:\n",++cnt); dfs(0); if(flag) { printf("YES\n"); for(int i=0;i<n;i++) { printf("%d",maze[i][0]); for(int j=1;j<m;j++) { printf(" %d",maze[i][j]); } printf("\n"); } } else printf("NO\n"); } return 0; }