POJ 1020 Anniversary Cake(dfs+分割思想)【转】

来源:互联网 发布:单片机编程要学什么 编辑:程序博客网 时间:2024/06/04 18:57

 

                                                             转自:YoU  http://blog.csdn.net/lyy289065406/article/details/6683250

Anniversary Cake

问题描述 :

Nahid Khaleh decides to invite the kids of the “Shahr-e Ghashang” to her wedding anniversary. She wants to prepare a square-shaped chocolate cake with known size. She asks each invited person to determine the size of the piece of cake that he/she wants (which should also be square-shaped). She knows that Mr. Kavoosi would not bear any wasting of the cake. She wants to know whether she can make a square cake with that size that serves everybody exactly with the requested size, and without any waste.

输入:

The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by input data for each test case. Each test case consist of a single line containing an integer s, the side of the cake, followed by an integer n (1 ≤ n ≤ 16), the number of cake pieces, followed by n integers (in the range 1..10) specifying the side of each piece.

输出:

There should be one output line per test case containing one of the words KHOOOOB! or HUTUTU! depending on whether the cake can be cut into pieces of specified size without any waste or not.

样例输入:

24 8 1 1 1 1 1 3 1 15 6 3 3 2 1 1 1

样例输出:

KHOOOOB!HUTUTU!

大致题意:

有一块边长为BoxSize的正方形的大蛋糕,现在给出n块不同尺寸的正方形的小蛋糕的边长,问是否能把大蛋糕按恰好切割为这n块小蛋糕,要求每块小蛋糕必须为整块。

 

解题思路:

有技巧的DFS

 

可以把大蛋糕想象为一个蛋糕盒子,然后往里面装小蛋糕。

装蛋糕时遵循以下原则:

自下而上,自左至右;

即先装好盒子底部,再继续往上层装,且装每一层时都靠左边放蛋糕;

大蛋糕优先装,因为小蛋糕灵活度比较高。

 

只要把问题变换为上述问题,我想对深搜比较熟悉的同学也会马上得到思路了,这个只是很简单的DFS思路。

 

但是本题的难点不在于怎样去DFS,而是每放入一个蛋糕后,怎样去标记盒子已经放有蛋糕的位置?

我初始的做这题时,因为看到数据规模不大(Max_n=16,Max_size=10,那么大蛋糕最大也就40*40),于是我把尺寸为BoxSize的盒子划分为BoxSize*BoxSize个1*1的格子,每放入一个大小为size的蛋糕,就用一个二重循环去标记size*size的格子。

最后是毫无悬念地TLE了。

看了别人的方法,发现或分格子的思路是正确的,但应该“按列标记”。不但把盒子看做多个1*1个格子,也把小蛋糕看做多个1*1的单位,建立一个一维数组col[ BoxSize ],每放入一个蛋糕,则去记录每列的格子被填充的数目。

例如在第2~4列放入了一个size=3的小蛋糕,那么col[2]+=3, col[3]+=3, col[4]+=3。有同学会问,为什么行不用计数?要是放入蛋糕后,该蛋糕底部出现部分悬空怎么处理?这个情况是不会出现的,因为当前DFS遵循先把底部放满原则,要是出现悬空,则会回溯。

代码:

//Memory Time //208K  32MS #include<iostream>using namespace std;int BoxSize;      //盒子尺寸int n;            //蛋糕的总个数int SizeNum[11];  //各种尺寸的蛋糕个数int col[41];      //把盒子纵行分割成BoxSize*BoxSize个1*1大小的小格子                  //col[i]记录第i列被填充了的格子数bool DFS(int FillNum)   //FillNum:已放入盒子的蛋糕数{if(FillNum==n)return true;/*寻找格子数被填充最少的列,靠左优先*/int min=50;int prow;for(int i=1;i<=BoxSize;i++)if(min>col[i]){min=col[i];prow=i;}/*枚举各种尺寸的蛋糕自下而上地放入盒子*/    for(int size=10;size>=1;size--){if(!SizeNum[size])continue;//检查尺寸为size的蛋糕放入盒子时在纵向和横向是否越界if(BoxSize-col[prow]>=size && BoxSize-prow+1>=size)        {//检查盒子从第prow列到第prow+size-1列,共size列的宽度wide中//是否每列剩余的空间都足够放入高度为size的蛋糕            int wide=0;            for(int r=prow;r<=prow+size-1;r++){if(col[r]<=col[prow])  //比较各列的"填充数"{    //注意,这里若比较"未填充数"BoxSize-col[r]<size会TLEwide++;       //虽然两个条件等价,但确实计算了3秒左右,不知何故continue;}break;}            if(wide>=size)            {int r;                //放入尺寸为size的蛋糕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(void){int test;cin>>test;for(int t=1;t<=test;t++){memset(SizeNum,0,sizeof(SizeNum));memset(col,0,sizeof(col));cin>>BoxSize>>n;int cnt=0;   //记录size>(BoxSize/2)的蛋糕个数int area=0;  //计算所有蛋糕的面积之和for(int i=1;i<=n;i++){int size;cin>>size;area+=size*size;SizeNum[size]++;if(size>BoxSize/2)cnt++;}if(cnt>1 || area!=BoxSize*BoxSize){cout<<"HUTUTU!"<<endl;continue;}if(DFS(0))cout<<"KHOOOOB!"<<endl;elsecout<<"HUTUTU!"<<endl;}return 0;}

ps:

因为自己写的严重tle。。所以就百度了,这个博主写的很好也易懂。。很懒的我就直接转载了


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 押金的收据丢了怎么办 房东的合同掉了怎么办 个人档案里单位没有放合同怎么办 签的合同掉了怎么办 一方合同弄丢了怎么办 合同丢了怎么办如何补 签了定金合同对方违约怎么办 医学出生证明丢了怎么办 易通行出站未刷怎么办 炭烧酸奶过期了怎么办 西安建行etc坏了怎么办 电机在设备壳体中拔不出来怎么办 公司变更股东不能亲临现场怎么办? 公司股东变更老股东不签字怎么办 公司变更地址股东不签字怎么办 公司变更股份股东不签字怎么办 公司股东离职股东没变更过来怎么办 河南省宋基投资公司欠钱怎么办 曲江楼观2O18怎么办 华旭金卡身份证扫描不了怎么办 水表里有钱没水怎么办? ff14过图速度慢怎么办 想让电表跑的慢怎么办 家里电表突然没有电了怎么办 电表不识别电卡怎么办 家里水表不转了怎么办 车管所体检色弱怎么办 煤气押金单没了怎么办 中国建设银行登录密码忘了怎么办 中国建设银行登录密码忘记了怎么办 公司车辆怎么办换新能源牌 杭州新能源汽车牌照外地人怎么办 建行登录密码忘了怎么办 新捷达epc灯亮怎么办 捷达车玻璃升降偏离怎么办 交金中断一个月怎么办 博士拟录取没导师怎么办 保研联系导师后怎么办 特别害怕和导师交流怎么办 面试工资要少了怎么办 一面工资要低了怎么办