我开始试着用dfs,结果超时,附代码。
/*
la 4794
*/
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define N 100+10
using namespace std;
struct node
{
int x;
int y;
int area;
};
node a[N];//存中间块
int b[N];//存目标面积
int x,y,n;
int mi;
bool cmp(node x,node y)
{
if(x.area<=y.area)
return true;
else
return false;
}
bool DFS(int l)
{
if(l==n)
{
// sort(a,a+n,cmp);//犯了个致命错误,一致递归的上一层的a[i]发生了变化
node c[N];
memcpy(c,a,n*sizeof(node));
sort(c,c+n,cmp);
for(int i=0;i<n;i++)
if(b[i]!=c[i].area)
return false;
return true;
}
for(int i=0;i<l;i++)
{
if(a[i].area<mi) return false;
if(a[i].area>mi)
{
//切x轴
node q=a[i];
for(int j=1;j<q.x/2+1;j++)//可以优化
{
node temp={j,q.y,j*q.y};
a[i]=temp;
a[l]={q.x-j, q.y, (q.x-j)*q.y};
if(DFS(l+1)==true)
return true;
a[i]=q;
}
a[i]=q;
//切y
for(int j=1;j<q.y+1;j++)
{
node temp={q.x, j, j*q.x};
a[i]=temp;
a[l]={q.x, q.y-j, (q.y-j)*q.x};
if(DFS(l+1)==true)
return true;
a[i]=q;
}
a[i]=q;
}
}
return false;
}
int main(int argc, char const *argv[])
{
// freopen("input","r",stdin);
// freopen("output","w",stdout);
int t=0;
while(scanf("%d",&n),t++,n)
{
scanf("%d%d",&y,&x);
for(int i=0;i<n;i++)
scanf("%d",&b[i]);
a[0]={x,y,x*y};
sort(b,b+n);
int sum=0;
for(int i=0;i<n;i++)
sum+=b[i];
mi=b[0];
if(sum==x*y && DFS(1)==1)
printf("Case %d: YES\n",t);
else
printf("Case %d: NO\n",t);
}
return 0;
}
dp:
看书写的
<pre name="code" class="cpp">#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=16;
const int maxw=100+10;
int n,a[maxn],sum[1<<maxn],f[1<<maxn][maxw],vis[1<<maxn][maxw];
int bit(int a)
{
return a==0 ? 0: bit(a/2)+ (a&1);//
}
int dp(int s,int x)
{
if(vis[s][x])
return f[s][x];
vis[s][x]=1;
int &ans=f[s][x];
//刚好为其中一块的情况
if(bit(s)==1)
return ans=1;
int y=sum[s]/x;
//枚举子集
for(int s0=(s-1) & s;s0;s0=(s0-1) & s)
{
int s1=s -s0;//int s1=s & ~s0;也行
if(sum[s0]%x==0 && dp(s0,min(x,sum[s0]/x) ) && dp(s1,min(x,sum[s1]/x) ) )
return ans=1;
if(sum[s0]%y==0 && dp(s0,min(y,sum[s0]/y)) && dp(s1,min(y,sum[s1]/y)) )
return ans=1;
}
return ans=0;
}
int main(int argc, char const *argv[])
{
// freopen("input","r",stdin);
int t=0,x,y;
while(scanf("%d",&n),t++,n)
{
scanf("%d%d",&x,&y);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
memset(sum,false,sizeof(sum));
for(int i=0;i< (1<<n);i++)
for(int j=0;j<n;j++)
if(i & 1<<j)
sum[i]+=a[j];
memset(vis,false,sizeof(vis));
int all=(1<<n)-1;
int ans;
if(sum[all]!=x*y || sum[all] % x!=0)
ans=0;
else
ans=dp(all,min(x,y));//
printf("Case %d: %s\n",t,ans ? "Yes":"No" );
}
return 0;
}