题目略
搜索剪枝 每次从左上角开始一行行找 找第一个空白位置 看能不能放下某个正方形 当产生完全覆盖之后即找到答案 类似方法的题还有zoj 3209
两点注意
1 先对19个正方形升序排序 只要某个没用过得正方形放不下了 后边的肯定放不下直接跳过(如果是矩形就没法这样贪心)
2 如果初始标定的三个正方形放在了左上角 找第一个空白位置就从左上开始 如果放在了右下角 那就从右下开始 不然在很长一段时间内搜索是基本没啥剪枝的 因为周围太空旷了 应该是直到与标定的三个正方形相遇之后剪枝才开始强力的
using namespace std;
const int maxn=200;
int book[maxn][maxn];
int ary[maxn],flag[maxn];
int num,gou;
void paint(int x,int y,int len,int val)
{
int i,j;
for(i=x;i<=x+len-1;i++){
for(j=y;j<=y+len-1;j++){
book[i][j]=val;
}
}
}
bool judge(int x,int y,int len)
{
int i,j;
if(x+len-1>154||y+len-1>154) return 0;
for(i=x;i<=x+len-1;i++){
for(j=y;j<=y+len-1;j++){
if(book[i][j]!=-1) return 0;
}
}
return 1;
}
bool dfs(int area)
{
int i,j,px,py;
/*
if(gou<10){
printf("*%d*\n",area);
gou++;
}
*/
if(area==23716) return 1;
for(i=1;i<=154;i++){
for(j=1;j<=154;j++){
if(book[i][j]==-1){
px=i,py=j;
break;
}
}
if(j!=155) break;
}
for(i=0;i<num;i++){
if(judge(px,py,ary[i])){
if(!flag[i]){
paint(px,py,ary[i],i);
flag[i]=1;
if(dfs(area+ary[i]*ary[i])) return 1;
paint(px,py,ary[i],-1);
flag[i]=0;
}
}
else break;
}
return 0;
}
int main()
{
int i,pre;
num=19;
2 5 9 11 16 17 19 21 22 24 26 30 31 33 35 36 41 50 52
for(i=0;i<num;i++){
scanf("%d",&ary[i]);
}
memset(book,-1,sizeof(book));
//47 46 61
paint(1,1,47,19);
paint(1,47+1,46,20);
paint(1,47+46+1,61,21);
if(dfs(8046)){
pre=-1;
for(i=1;i<=154;i++){
if(book[154][i]!=pre){
pre=book[154][i];
printf("%d ",ary[book[154][i]]);
}
}
printf("\n");
}
else printf("gg\n");
return 0;
}