您的位置:首页 > 其它

poj 2923 状态压缩 + 01背包

2012-11-29 10:54 337 查看
题意:

两个车有容量a与b,n个物品,每个物品有一个体积,问最小多少次能够运完他们。

因为n<10,所以可以用状态压缩。

先进行遍历,看看1<<n这些状态能不能一次运完。能的话加入it数组里。

然后用it数组,代表物品,进行背包 j代表状态,j&it[i]时,代表两个状态不冲突,就是存在某个物品运了两次。j|it[i]代表当前状态。

#include<stdio.h>
#include<string.h>
#define Max 10000000
int it[2000],dp[2000],n,ai[20],a,b,sum;
int min(int a,int b){
return a<b?a:b;
}
bool find(int x){
int su=0;
bool vis[2000];
memset(vis,0,sizeof(vis));
vis[0]=1;
for(int i=0;i<n;i++){
if(1<<i&x){
su+=ai[i];
for(int j=a;j>=ai[i];j--){
if(vis[j-ai[i]]){
vis[j]=1;
}
}
}
}
if(su>a+b){
return false;
}
for(int i=0;i<=a;i++){
if(vis[i]&&su-i<=b){
return true;
}
}
return false;
}
int main(){
int cas;
scanf("%d",&cas);
int kk=1;
int k=0;
while(cas--){
k=0;
scanf("%d%d%d",&n,&a,&b);
for(int i=0;i<n;i++){
scanf("%d",&ai[i]);
}
for(int i=1;i<(1<<n);i++){
if(find(i)){
it[k++]=i;
}
}
for(int i=0;i<(1<<n);i++){
dp[i]=Max;
}
dp[0]=0;
printf("Scenario #%d:\n",kk++);
for(int i=0;i<k;i++){
for(int j=(1<<n)-1;j>=0;j--){
if(dp[j]==Max){
continue;
}
if((j&it[i])==0){
dp[j|it[i]]=min(dp[j|it[i]],dp[j]+1);
}
}
}
printf("%d\n\n",dp[(1<<n)-1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: