本题的难点不在于怎样去DFS,而是每放入一个蛋糕后,怎样去标记盒子已经放有蛋糕的位置?
#include <stdio.h>
#include <string.h>
int boxsize,n,sizenum[11],col[41]; //col[i]记录第i列被填充了的格子数
bool DFS(int fillnum)
{
if (fillnum==n)
return true;
int min=2147483647,prow; //寻找格子数被填充最少的列,靠左优先
for (int i=1; i<=boxsize; i++)
if (min>col[i])
{
min=col[i]; prow=i;
}
for (int size=10; size!=0; size--)
{
if (!sizenum[size])
continue;
if (boxsize-col[prow]>=size && boxsize-prow+1>=size) //检查尺寸为size的蛋糕放入盒子时在纵向和横向是否越界
{
int wide=0;
/*检查盒子从第prow列到第prow+size-1列,共size列的宽度wide中
是否每列剩余的空间都足够放入高度为size的蛋糕 */
for (int r=prow; r<=prow+size-1; r++)
if (col[r]<=col[prow])
wide++;
else
break;
if (wide>=size)
{
int r;
sizenum[size]--;
for (r=prow; r<=prow+size-1; r++)
col[r]+=size;
if (DFS(fillnum+1))
return true;
sizenum[size]++;
for (r=prow; r<=prow+size-1; r++)
col[r]-=size;
}
}
}
return false;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
memset(sizenum,0,sizeof(sizenum));
memset(col,0,sizeof(col));
scanf("%d%d",&boxsize,&n);
int cnt=0,area=0;
for (int i=1; i<=n; i++)
{
int size;
scanf("%d",&size);
area+=size*size;
sizenum[size]++;
if (size>boxsize/2)
cnt++;
}
if (cnt>1 || area!=boxsize*boxsize)
{
printf("HUTUTU!\n"); continue;
}
if (DFS(0))
printf("KHOOOOB!\n");
else
printf("HUTUTU!\n");
}
return 0;
}