题目大意:给定一个长为w,宽为h,的巧克力,再给定一个面积的集合,问巧克力能不能完全分割成给定的面积的集合?(面积集合的大小小于等于15)
解题思路:对给定的面积集合用状态枚举子集,在利用记忆化搜索判断能够分解成给定的集合
#include <iostream>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 16;
const int MAXS = 1<<MAXN;
int n,x,y,s[MAXN];
int d[MAXS][MAXN],sum[MAXS];
bool init()
{
scanf("%d",&n);
if(n==0)return false;
scanf("%d%d",&x,&y);
for(int i=0;i<n;i++)scanf("%d",s+i);
memset(d,-1,sizeof(d));
memset(sum,0,sizeof(sum));
return true;
}
int bitcount(int x)
{
int res = 0;
while(x)
{
res += x&1;
x>>=1;
}
return res;
}
int dp(int S,int x)
{
if(d[S][x]!=-1)
{
return d[S][x];
}
int& ans =d[S][x];
if(bitcount(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;
if(sum[S0]%x==0 && dp(S1,min(sum[S1]/x,x)) && dp(S0,min(x,sum[S0]/x)))
return ans =1;
if(sum[S0]%y==0 && dp(S1,min(sum[S1]/y,y)) && dp(S0,min(sum[S0]/y,y)))
return ans =1;
}
return ans =0;
}
ofstream fout("my.txt");
void solve()
{
int bound = 1<<n;
for(int S=0;S<bound ;S++)
{
for(int i=0;i<n;i++)
{
if(S&(1<<i))
{
sum[S]+= s[i];
}
}
}
bound--;
int ans =-1;
if(sum[bound]!= x*y || sum[bound]%x!=0)ans=0;
else {
ans = dp(bound,min(x,y));
}
printf("%s\n",ans?"Yes":"No");
for(int i=0;i<=min(x,y);i++)
{
for(int j=0;j<=bound;j++)
{
fout <<"dp["<<i<<"]["<<j<<"]="<<d[i][j]<<" ";
}
fout<<endl;
}
}
int main()
{
int ks = 1;
while(init())
{
printf("Case %d: ",ks++);
solve();
}
return 0;
}