hdu 5113 Black And White(深搜+剪枝)

来源:互联网 发布:复旦大学软件学院就业 编辑:程序博客网 时间:2024/05/29 04:33
In mathematics, the four color theorem, or the four color map theorem, states that, given any separation of a plane into contiguous regions, producing a figure called a map, no more than four colors are required to color the regions of the map so that no two adjacent regions have the same color. 
— Wikipedia, the free encyclopedia 

In this problem, you have to solve the 4-color problem. Hey, I’m just joking. 

You are asked to solve a similar problem: 

Color an N × M chessboard with K colors numbered from 1 to K such that no two adjacent cells have the same color (two cells are adjacent if they share an edge). The i-th color should be used in exactly c i cells. 

Matt hopes you can tell him a possible coloring.

intput:

The first line contains only one integer T (1 ≤ T ≤ 5000), which indicates the number of test cases. 

For each test case, the first line contains three integers: N, M, K (0 < N, M ≤ 5, 0 < K ≤ N × M ). 

The second line contains K integers c i (c i > 0), denoting the number of cells where the i-th color should be used. 

It’s guaranteed that c 1 + c 2 + · · · + c K = N × M .

output:

For each test case, the first line contains “Case #x:”, where x is the case number (starting from 1). 

In the second line, output “NO” if there is no coloring satisfying the requirements. Otherwise, output “YES” in one line. Each of the following N lines contains M numbers seperated by single whitespace, denoting the color of the cells. 

If there are multiple solutions, output any of them.

Sample Input

41 5 24 13 3 41 2 2 42 3 32 2 23 2 32 2 2
Sample Output

Case #1:NOCase #2:YES4 3 42 1 24 3 4Case #3:YES1 2 32 3 1Case #4:YES1 22 33 1
大意是有N*M个格子,给出k种颜色,然后规定每种颜色必须使用多少次,还要保证染色的格子不能与周围四个格子颜色相同。

开始想用广搜,后来觉得如果颜色不合适,再回来改颜色的时候不好操作,于是用深搜按照从左到右的顺序搜索。

#include<stdio.h>#include<cstring>using namespace std;int map[6][6];int ans[36];int color[26];int mv[2][2]={{0,-1},{-1,0}};//因为搜索的顺序,所以只需要判断左边和上边的染色是否相同就可以int sum;int n,m,k;int flag=0;void dfs(int );bool ican(int,int,int);int main(){int t;int cnt=1;scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=k;i++)scanf("%d",&color[i]);sum=n*m;printf("Case #%d:\n",cnt);//printf("sum=%d\n",sum);memset(map,0,sizeof(map));flag=0;dfs(1);if(flag==0)printf("NO\n");cnt++;}return 0;}void dfs(int ii){if(flag==1)return;for(int i=1;i<=k;i++){if(color[i]>(sum-ii+2)/2)//如果剩余的格子数加一小于某种颜色的剩余次数的二倍就一定不行。。{return;}}int x,y;x=ii/m+1;if(ii%m==0){x=ii/m;y=m;}else{x=ii/m+1;y=ii%m;}//printf("x=%d,y=%d\n",x,y);if(ii==sum+1){flag=1;printf("YES%\n");int j=0;for(int i=1;i<=sum;i++){printf("%d",ans[i]);j++;if(j!=m)printf(" ");else{printf("\n");j=0;}}return;}for(int i=1;i<=k;i++){//printf("x=%d,y=%d\n",x,y);if(ican(x,y,i)){map[x][y]=i;color[i]--;ans[ii]=i;dfs(ii+1);if(flag)return;map[x][y]=0;color[i]++;}}if(map[x][y]==0)return;}bool ican(int x,int y,int c){int xt,yt;if(color[c]==0)return false;for(int j=0;j<2;j++){xt=x+mv[j][0];yt=y+mv[j][1];if(xt<1||yt<1||xt>n||yt>m)continue;if(map[xt][yt]==c)return false;}return true;}