1. 程式人生 > >[DFS] 小矩陣限定顏色數量不相鄰填色 HDU5113

[DFS] 小矩陣限定顏色數量不相鄰填色 HDU5113

Black And White

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 6000    Accepted Submission(s): 1644
Special Judge

 

Problem 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 ci 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 ci (ci > 0), denoting the number of cells where the i-th color should be used.

It’s guaranteed that c1 + c2 + · · · + cK = 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

 

 

Source

2014ACM/ICPC亞洲區北京站-重現賽(感謝北師和上交)

 

#include <bits/stdc++.h>
using namespace std;

int n, m, k;
bool ans;

int a[30], mp[6][6];
void dfs(int x, int y)
{
	if (x == n + 1 && y == 1)
	{
		ans = 1; 
		return;
	}
	
	for (int i = 1; i <= k; i++)
		if ((n - x + 1) * m - y + 1 < 2 * a[i] - 1)
			return;
	// 存在插空填會溢位的顏色 情況不可能 回溯
	
	for (int i = 1; i <= k; i++)
	{
		if (a[i] <= 0) // 無餘量
			continue;
		if ((mp[x - 1][y] == i) || mp[x][y - 1] == i) // 相鄰
			continue;
			
		mp[x][y] = i;
		a[i] --;
		if (y == m)
			dfs(x + 1, 1);
		else 
			dfs(x, y + 1);
		
		if (ans) 	// 情況合法, 回溯 
			return;
		
		mp[x][y] = 0;
		a[i]++;
		// 失敗 清空嘗試下一種情況
	}
	return;
}
int main()
{
	int T;
	scanf("%d", &T);
	for (int cas = 1; cas <= T; cas++)
	{
		ans = 0;
		memset(mp, 0, sizeof mp);
		printf("Case #%d:\n", cas);

		scanf("%d %d %d", &n, &m, &k);
		for (int i = 1; i <= k; i++)
			scanf("%d", &a[i]);
		
		dfs(1, 1);
		/// DFS 嘗試可能情況
		
		if (ans == 0)
			printf("NO\n");
		else 
		{
			printf("YES\n");
			for (int i = 1; i <= n; i++)
			{
				for (int j = 1; j < m; j++)
					printf("%d ", mp[i][j]);
				printf("%d\n", mp[i][m]);
			}
		}
	}
	return 0;
}