如题:http://poj.org/problem?id=1020
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 15696 | Accepted: 5120 |
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!
Source
一开始的思路是毫无剪枝的强行深搜,虽然知道应该会超,但还是试了试。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int need[20];
int map[200][200];
int cmp(int &a,int &b)
{
return a>b;
}
int judge(int x,int y,int pos)
{
int i,j;
if(x+need[pos]-1>n||y+need[pos]-1>n)
return 0;
for(i=x;i<x+need[pos];i++)
for(j=y;j<y+need[pos];j++)
if(map[i][j])
return 0;
return 1;
}
int dfs(int pos) //将第pos个小正方形放进
{
if(pos==m)
{
return 1;
}
int i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(judge(i,j,pos))
{
for(k=i;k<i+need[pos];k++)
for(l=j;l<j+need[pos];l++)
map[k][l]=1;
if(dfs(pos+1))
return 1;
for(k=i;k<i+need[pos];k++)
for(l=j;l<j+need[pos];l++)
map[k][l]=0;
}
}
return 0;
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
int t;
cin>>t;
int i;
while(t--)
{
scanf("%d",&n);
scanf("%d",&m);
int s=0;
for(i=0;i<m;i++)
{
scanf("%d",&need[i]);
s+=need[i]*need[i];
}
if(s!=n*n)
{
printf("HUTUTU!\n");
continue;
}
sort(need,need+m,cmp);
memset(map,0,sizeof(map));
if(dfs(0))
printf("KHOOOOB!\n");
else
printf("HUTUTU!\n");
}
return 0;
}
之后看了别人的报告,受益匪浅。
每一次找到一个合适的位置,放进这个位置能放的最大一个方块。
col[i]数组代表第i列里有单位为1的蛋糕块的数量。
放蛋糕的方法:从左到右扫描出列,单位蛋糕最少的那一列,然后选择一个能放入的尽量大的放块放入。小方块最后放。
通过col数组和一种放方块的正确方法大大减少了搜索的复杂度。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int sizenum[11];
int col[200];
int dfs(int num) //已经装入的蛋糕数量。满足每次选一个最大的装入。从
{
if(num==m)
return 1;
int mincol=0;
int min=200;
int i,j;
for(i=1;i<=n;i++)
{
if(col[i]<min)
{
min=col[i];
mincol=i;
}
}
for(i=10;i>=1;i--)
{
if(sizenum[i]&&n-min>=i&&n-mincol+1>=i)
{
int w=1;
for(j=mincol+1;j<mincol+i;j++)
{
if(col[j]<=min)
{
w++;
continue;
}
break; //不连续.
}
if(w>=i)
{
sizenum[i]--;
for(j=mincol;j<mincol+i;j++)
col[j]+=i;
if(dfs(num+1))
return 1;
sizenum[i]++;
for(j=mincol;j<mincol+i;j++)
col[j]-=i;
}
}
}
return 0;
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
int t;
cin>>t;
int i;
while(t--)
{
memset(sizenum,0,sizeof(sizenum));
memset(col,0,sizeof(col));
cin>>n;
cin>>m;
int s=0;
for(i=0;i<m;i++)
{
int size;
scanf("%d",&size);
sizenum[size]++;
s+=size*size;
}
if(s!=n*n)
{
printf("HUTUTU!\n");
continue;
}
if(dfs(0))
printf("KHOOOOB!\n");
else
printf("HUTUTU!\n");
}
return 0;
}