原题链接: http://acm.hdu.edu.cn/showproblem.php?pid=5113
题意:
一个n*m的矩阵,给定n*m个颜色,颜色一共有k种,每种a[ i ]个,现在要你把所有颜色填到矩阵中,要求相邻(也就是上下左右)颜色不重复。
很明显的深搜,不过这深搜是一个一个去找,每个必须配颜色,所以对于当前点,查找的方向就是两个,一是当前行,列加1,二是走至行尾,开始走下一行的第一列。所以这题不用开数组dir保存四个方向。
另外剪枝,如果走到当前点,发现还没有填充的点的一半比剩下颜色的最大值还小,那肯定不可以的,读者可以画图看一下。另外贴下AC代码:
#define _CRT_SECURE_NO_DEPRECATE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int p[6][6];
int a[30];
int t, n, m, k;
int flag;
void dfs(int x, int y, int color)
{
for (int i = 1; i <= k; i++)//剪枝
if (a[i] > ((n - x)*m + m - y + 1) / 2)
return;
p[x][y] = color;
if (x == n&&y == m)
{
flag = 1;
return;
}
if (y + 1 <= m)//往前走一步,不越界的话
{
int xx = x;
int yy = y + 1;
int i;
for (i = 1; i <= k; i++)
{
if (a[i] && i != p[xx][yy - 1] && i != p[xx - 1][yy])//颜色还有,左边,上边颜色不重复
{
a[i] --;
dfs(xx, yy, i);
if (flag == 1)
return;
a[i]++;
}
}
}
else if (x + 1 <= n)
{
int xx = x + 1;
int yy = 1;
int i;
for (i = 1; i <= k; i++)
{
if (a[i] && i != p[xx - 1][yy])//颜色还有,左边,上边颜色不重复
{
a[i] --;
dfs(xx, yy, i);
if (flag == 1)
return;
a[i]++;
}
}
}
}
int main()
{
scanf("%d", &t);
for (int cas = 1; cas <= t; cas++)
{
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= k; i++)
scanf("%d", &a[i]);
flag = 0;
memset(p, 0, sizeof(p));
for (int i = 1; i <= k; i++)
{
a[i]--;
dfs(1, 1, i);
if (flag == 1)
break;
a[i]++;
}
if (flag)
{
printf("Case #%d:\nYES\n", cas);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (j == m)
printf("%d\n", p[i][j]);
else
printf("%d ", p[i][j]);
}
}
}
else
printf("Case #%d:\nNO\n", cas);
}
return 0;
}