您的位置:首页 > 其它

UVA 1099【状态压缩】

2016-03-24 21:41 288 查看
题意:有一块x*y的巧克力,问你是否可以分成n块大小分别为aI的小巧克力

分析:n<=15,很小,可以用二进制记录每种组合情况,定义dp[s][x]表示s集合的巧克力能否组成边长为x的大巧克力。

然后枚举s的子集,判断子集能否构成。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1<<15
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[20];
int sum[Mn];
int dp[Mn][105];
int lowbit(int x) {
return x&(-x);
}
int countbit(int x) {
int re=0;
while(x) {
re++;
x-=lowbit(x);
}
return re;
}
int dfs(int s,int x) {
if(dp[s][x]!=-1) return dp[s][x];
if(countbit(s)==1) return dp[s][x]=1;
int y=sum[s]/x;
dp[s][x]=0;
for(int s0=(s-1)&s;s0;s0=(s0-1)&s) {
int s1=s^s0;
if(sum[s0]%x==0&&dfs(s0,min(x,sum[s0]/x))&&dfs(s1,min(x,sum[s1]/x)))
return dp[s][x]=1;
if(sum[s0]%y==0&&dfs(s0,min(y,sum[s0]/y))&&dfs(s1,min(y,sum[s1]/y)))
return dp[s][x]=1;
}
return dp[s][x]=0;
}
int main() {
int n,x,y,cas=0;
while(scanf("%d",&n)) {
if(n==0) break;
cas++;CLR(sum,0);
scanf("%d%d",&x,&y);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int s=1;s<(1<<n);s++)
for(int i=0;i<n;i++)
if(s&(1<<i)) sum[s]+=a[i];
int flag=1;
int all=(1<<n)-1;CLR(dp,-1);
if(sum[all]!=x*y||sum[all]%x) flag=0;
else if(!dfs(all,min(x,y))) flag=0;
printf("Case %d: ",cas);
if(flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: