poj 1020 Anniversary Cake(切正方形蛋糕+搜索)

                                                                                                               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.

Input

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.

Output

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.

Sample Input

2
4 8 1 1 1 1 1 3 1 1
5 6 3 3 2 1 1 1

Sample Output

KHOOOOB!
HUTUTU!

题意:将一个大的正方形的蛋糕恰好切成多个小正方形,问能否做到。
解析:首先判断所有小正方形的面积之和是否等于大正方形,不等肯定不行。还有如果小正方形中存在两个最大的边长之和大于大正方形,肯定也不行。搜索的话,由于小正方形的边长最大为10,而且最多只有16个,因此大正方形的边长最大为40
那么我从底层开始一层层往上铺,用一个col[]数组保存这一列对应的高度,要铺的话总是找col[]中最小最左边的(铺最低的地方)还要判断能不能铺某个正方形,直到所有正方形铺完。

代码如下:
#include<cstdio>
#include<cstring>
#include<string> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #include<iterator> #include<utility> #include<sstream> #include<iostream> #include<cmath> #include<stack> using namespace std; const int INF=1000000007; const double eps=0.00000001; int edge,N; int H[11],col[41]; bool dfs(int cur) { if(cur==N) return true; //铺完了 int minX=50,pos; for(int i=1;i<=edge;i++) if(col[i]<minX) { minX=col[i],pos=i; } //找到最低最靠左的位置 for(int i=10;i>=1;i--) //枚举正方形高度 { if(!H[i]) continue; if(minX+i<=edge&&pos+i<=edge+1) //不能越界 { bool ok=true; for(int st=pos;st<pos+i;st++) //还要判断能不能铺 { if(col[st]>col[pos]){ ok=false; break; } } if(ok) { for(int st=pos;st<pos+i;st++) col[st]+=i; //铺的位置全部加上这个高度 H[i]--; //删掉这个正方形 if(dfs(cur+1)) return true; H[i]++; for(int st=pos;st<pos+i;st++) col[st]-=i; } } } return false; } int main() { int T; cin>>T; while(T--) { cin>>edge>>N; memset(H,0,sizeof(H)); memset(col,0,sizeof(col)); int sum=0,cnt=0; for(int i=1;i<=N;i++) { 

转载于:https://www.cnblogs.com/wust-ouyangli/p/4765717.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值