题目大意:
思路:这里分的时候是把集合分成两个,并且把这个矩阵块分成两个。分别等于这两个集合的矩阵和,当一个集合只有一个元素,那么就满足条件了。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int a[20];
int d[1<<20][150], sum[1<<20], vis[1<<20][150];
int ok(int s){
return s==0?0:ok(s/2)+s%2;
}
int dp(int s, int x){
if(vis[s][x]){
return d[s][x];
}
int &ans=d[s][x];
vis[s][x]=1;
if(ok(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(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 T=1, n, x, y;
while(scanf("%d", &n)==1&&n){
scanf("%d%d", &x, &y);
for(int i=0; i<n; i++){
scanf("%d", &a[i]);
}
memset(sum, 0, sizeof(sum));
for(int s=0; s<(1<<n); s++){
for(int i=0; i<n; i++){
if(s&(1<<i)){
sum[s]+=a[i];
}
}
}
memset(d, 0, sizeof(d));
memset(vis, 0, 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;
}