Description
Input
Output
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! 题意: 有一块面积M X M的平面蛋糕 问是否能分成N块给定面积为a X a的蛋糕 首先应该换个思路理解题目 能否分成N块 == 能否恰用N块填充满 然后再按常规搜索思路给出填充策略 : 1.先下后上 先左后右 2.先填充大的蛋糕再填充小的 接着开始搜索了, 直接将蛋糕理解为二维数组去搜索是不行的耗时而且麻烦 我们可以给出一个数组 column[N] 表示每列填充了几个1X1的小蛋糕 要判断 能否填充一个a X a蛋糕(假设从J列开始) 只需要判断col[j]~col[j+a-1] 是否都满足 M-col[x]>=a 即可 按上述策略搜索即可得到答案 另注意两个剪枝: 大蛋糕的面积!=所有小蛋糕的面积之和时 肯定不行 边长比大蛋糕的边长的二分之一长的小蛋糕数量大于一时肯定不行 (可画图理解) 代码:#include<iostream> #include<cstdio> #include<cstring> using namespace std; int sumsize,n; int col[45],sizenum[12]; //MAXarea=1600 sizenum 表示这个size的数量 int dfs(int filled) { if(filled==n) return 1; int i,j,minn=20; for(i=1; i<=sumsize; i++) //找填充最少的列开始填充 { if(col[i]<minn) { minn=col[i]; j=i; } } for(int size=10;size>=1;size--) { if(sizenum[size]) { if(sumsize-minn>=size&&sumsize+1-j>=size) { int wide=0; for(i=j;i<j+size;i++) //判断横方向能否填充 { if(col[i]<=minn) { wide++; continue; } break; } if(wide>=size) { sizenum[size]--; //填充 for(i=j;i<j+size;i++) col[i]+=size; if(dfs(filled+1)) return 1; sizenum[size]++; //回溯 for(i=j;i<j+size;i++) col[i]-=size; } } } } return 0; } int main() { int t; int size; int area,s; scanf("%d",&t); while(t--) { s=area=0; memset(sizenum,0,sizeof(sizenum)); memset(col,0,sizeof(col)); scanf("%d%d",&sumsize,&n); for(int i=1; i<=n; i++) { scanf("%d",&size); sizenum[size]++; if(size>sumsize/2) s++; area+=size*size; } if(s>1||area!=sumsize*sumsize) //两个剪枝 { cout<<"HUTUTU!"<<endl; continue; } else { if(dfs(0)) cout<<"KHOOOOB!"<<endl; else cout<<"HUTUTU!"<<endl; } } return 0; }
原文地址:http://blog.csdn.net/axuan_k/article/details/42736651