把二维降到一维,有助于操作
本题是用列的累积表达整个区域
例如在2~3列放一个大小为三的蛋糕,visit【i】++;(1<i<=4)
然后就是寻找比较好的位置进行放蛋糕。
放蛋糕的时候又要注意判断是不是可以放的下
对于成功放入的进行下一步搜索,否则回溯,这里可以把回溯的概念理解清楚
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int s,n;
int a[15];
int visit[50];
bool dfs(int num)
{
if(num==n)
return true;
//寻找格子空位最多的,左优先
int pos,minx=50;
for(int i=1;i<=s;i++)
if(minx>visit[i]){
minx=visit[i];
pos=i;
}
//枚举不同大小的蛋糕(从大到小)
for(int i=10;i>0;i--){
if(!a[i])
continue;//去除为0的大小的蛋糕
//检查范围(i大小的蛋糕是否超出范围)
if(s-visit[pos]>=i&&s-pos+1>=i){
/*下面检查盒子从第pos列到第pos+i-1列,共i列的宽度wide中
是否每列剩余的空间都足够放入高度为i的蛋糕*/
int wide=0;
for(int j=pos;j<=pos+i-1;j++){
if(visit[j]<=visit[pos]){
wide++;
continue;
}
break;
}
if(wide>=i)//成功放入
{
a[i]--;
for(int j=pos;j<=pos+i-1;j++)
visit[j]+=i;
if(dfs(num+1))
return true;
//回溯
a[i]++;
for(int j=pos;j<=pos+i-1;j++)
visit[j]-=i;
}
}
}
return false;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
//初始化一切
scanf("%d%d",&s,&n);
memset(a,0,sizeof(a));
memset(visit,0,sizeof(visit));
//开始处理输入的数据
int coun=0,temp,area=0;
for(int i=0;i<n;i++){
scanf("%d",&temp);
a[temp]++;//合并可以减少排序
area+=temp*temp;
if(temp>s/2)
coun++;
}
//减枝
if(coun>1||area!=s*s){
printf("HUTUTU!\n");
continue;
}
if(dfs(0))
printf("KHOOOOB!\n");
else
printf("HUTUTU!\n");
}
return 0;