**
航电oj:Anniversary Cake
**
#题目描述
#给你n个数据,每个数据中有盒子边长,小蛋糕数,每个小蛋糕的边长
把题看成将小蛋糕塞进盒子里
#知识点
dfs算法
#代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n,boxlen;//数据次数,小蛋糕数,盒子长度
int cakenum[11],len[41];//cakenum 各个长度的蛋糕的个数 len 每一列的已填充的格子数
int nowsize,area,damageflag;//当前的小蛋糕长度,小蛋糕的面积和,危险标记
bool dfs(int count)
{
if(count == n)
return true;
///找最小的len列的序号
int minn = 0x3f3f3f3f,flag;//最小值初始化,最小列的开始标记数
for(int i=1;i<=boxlen;i++)///从左往右
{
if(len[i]<minn)
{
minn = len[i];
flag = i;
}
}
//已经找到该填充的位置,现在找填充的蛋糕
for(int size = 10;size >=1;size--)///size 当前选中的蛋糕的尺寸
{
if(!cakenum[size])//没有这一号尺寸的蛋糕了就换成小一号的
continue;
///
if(boxlen - len[flag]>= size&&boxlen - flag + 1 >= size)///放置的位置的空余位置要足够放下这个尺寸的蛋糕(宽和高)(左下角开始)///!!!
{
int wide =0;///用于计数, 记下从flag开始长度为size的这一段距离中的每一列的空余长度满足放置的数
for(int i = flag;i<= flag + size -1;i++)
{
if(len[i]<=len[flag])
wide ++;
else
break;///如果有还有没有足够位置的列,直接pass
}
///
if(wide >= size)
{
///准备将蛋糕放入盒子
cakenum[size]--;
for(int i = flag;i<=flag + size - 1;i++)
{
len[i]+=size;
}
///将蛋糕放入盒子 加 判断 如果没有判断就无法输出结果回去
if(dfs(count + 1))
return true;
///一次尝试失败了 复原数据///!!!!
cakenum[size]++;
for(int i = flag;i<=flag + size - 1;i++)
{
len[i]-=size;
}
}
}
}
return false;
}
int main()
{
scanf("%d",&t);
while(t--)
{
area = 0;//制零 好判断
damageflag = 0;
memset(cakenum,0,sizeof(cakenum));
memset(len,0,sizeof(len));
scanf("%d%d",&boxlen,&n);
///
for(int i=1; i<=n; i++)
{
scanf("%d",&nowsize);
area += nowsize*nowsize;
cakenum[nowsize]++;//哈希方式的存储数据
if(nowsize>boxlen/2)
damageflag ++;
}
///
if(area != boxlen*boxlen||damageflag > 1)///!!!!
{
printf("HUTUTU!\n");
continue;
}
if(dfs(0))
{
printf("KHOOOOB!\n");
continue;
}
else
{
printf("HUTUTU!\n");
continue;
}
}
return 0;
}
#总结
dfs 的题要记得返回原状