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
//关键剪枝: 当某种颜色的数量大于剩下格子数的一半时,就直接返回,
//因为这种情况一定会有相邻的颜色相同的情况
#include<stdio.h>
#include<string.h>
int a[10][10];
int c[50];
int n,m,k,flag;
void dfs(int x,int y,int v)
{
int i;
if(v==0)//所有格都填满了
{
flag=1;
return ;
}
for(i=1;i<=k;i++)
{
if(c[i]>(v+1)/2)//剪枝
return ;
}
for(i=1;i<=k;i++)
{
if(c[i]!=0)
{
if(a[x][y-1]!=i&&a[x-1][y]!=i)
{
a[x][y]=i;
c[i]--;
if(y==m)
dfs(x+1,1,v-1);
else
dfs(x,y+1,v-1);
if(flag==1)
return ;
c[i]++;
a[x][y]=0;
}
}
}
}
int main()
{
int t,i,j,u=0;
scanf("%d",&t);
while(t--)
{
u++;flag=0;
scanf("%d %d %d",&n,&m,&k);
for(i=1;i<=k;i++)
scanf("%d",&c[i]);
memset(a,0,sizeof(a));
dfs(1,1,n*m);
printf("Case #%d:\n",u);
if(flag==0)
printf("NO\n");
else
{
int f=0;
printf("YES\n");
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
printf("%d",a[i][j]);
if(j!=m)
printf(" ");
}
printf("\n");
}
}
}
return 0;
}
4457

被折叠的 条评论
为什么被折叠?



