hdu--5113 Black And White(dfs+剪枝)

Description

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.

Input

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

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
题意:大小为n*m的地图,用k种颜色进行涂色,每种颜色的使用次数为 Ci ,是否存在一种方案能将地图涂色为每个点的颜色都和它的上下左右都不相同,若有的话打印其中一种方案。
思路:判断颜色 i (1--k)是否能够放在点地图是s[step/m][step%m](0--n*m-1)上,如果能进行step+1的搜索,否则对颜色i+1进行判断。
剪枝方法:注意到当 剩余颜色个数的最大值 比(未涂色点数 + 1 )/2 大时无论如何涂色都会有颜色相邻,所以可以在每次搜索前进行判断。
AC代码:
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 int s[10][10];
 6 int book[100],a[100];
 7 int n,m,t,k,flag;
 8 void dfs(int step)
 9 {
10     if(flag)
11         return ;
12     if(step==n*m)
13     {
14         printf("YES\n");
15         for(int i=0; i<n; i++)
16         {
17             for(int j=0; j<m-1; j++)
18                 printf("%d ",s[i][j]);
19             printf("%d\n",s[i][m-1]);
20         }
21         flag=1;
22         return ;
23     }
24     for(int i=1; i<=k; i++)
25         if(a[i]>(n*m-step+1)/2)
26             return ;
27     for(int i=1; i<=k; i++)
28     {
29         if(a[i]<1)
30             continue;
31         if((s[step/m-1][step%m]==i&&step/m>0)||(s[step/m][step%m-1]==i&&step%m>0))
32             continue;
33         else
34         {
35             a[i]--;
36             s[step/m][step%m]=i;
37             dfs(step+1);
38             a[i]++;
39             s[step/m][step%m]=0;
40         }
41     }
42     for(int i=1; i<=k; i++)
43         if(a[i]!=0)
44             return ;
45     return ;
46 }
47 int main()
48 {
49     while(~scanf("%d",&t))
50     {
51         for(int p=1; p<=t; p++)
52         {
53             scanf("%d%d%d",&n,&m,&k);
54             for(int i=1; i<=k; i++)
55                 scanf("%d",&a[i]);
56             memset(s,0,sizeof(s));
57             flag=0;
58             printf("Case #%d:\n",p);
59             dfs(0);
60             if(!flag)
61                 printf("NO\n");
62         }
63     }
64     return 0;
65 }
View Code

心得体会:在搜索时要注意代码何时跳出,如何跳出的问题

posted @ 2016-10-19 16:52  Wally的博客  阅读(161)  评论(0编辑  收藏  举报