#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 16 ;
int n,sum[1<<maxn],a[maxn];
int vis[1<<maxn][110],dp[1<<maxn][110];
//假定 r<=c ,sum[s] 为该集合中的元素之和,dp[s][r] r行c列是否切割成面积集合s是否可行
//dp[s][r]=1的状态如下
//存在s的子集s0 使得 r0<r 使得dp[s0][r0]=dp[s0^s][r-r0]=1;
//存在s的子集s0 使得 c0<c 使得dp[s0][c0]=dp[s0^s][c-c0]=1;
int bit(int s)//计算集合中的元素个数
{
return s?bit(s>>1)+(s&1):0;
}
int DP(int s,int r)
{
if(vis[s][r]) return dp[s][r];
vis[s][r]=1;
if(bit(s)==1) return dp[s][r]=1;
int c=sum[s]/r;
for(int s0=(s-1)&s;s0;s0=(s0-1)&s)
{
if(sum[s0]%r==0 && DP(s0,min(r,sum[s0]/r)) && DP((s0^s),min(r,sum[s0^s]/r)))
return dp[s][r]=1;
if(sum[s0]%c==0 && DP(s0,min(c,sum[s0]/c)) && DP((s0^s),min(c,sum[s0^s]/c)))
return dp[s][r]=1;
}
return dp[s][r]=0;
}
int main()
{
int cas=1,x,y;
while(~scanf("%d",&n)&&n)
{
scanf("%d%d",&x,&y);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int all = (1<<n)-1;
for(int s=0;s<=all;s++)
{
sum[s]=0;
for(int i=0;i<n;i++)
if(s&(1<<i)) sum[s]+=a[i];
}
clr(vis,0);
int ans;
if(sum[all]!=x*y) ans=0;
else ans=DP(all,min(x,y));
printf("Case %d: %s\n",cas++,ans?"Yes":"No");
}
}
UVA 1099 Sharing Chocolate
最新推荐文章于 2016-03-20 11:54:03 发布