hdu 1059 Dividing (多重背包详解)
2018-01-31 14:19
316 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1059
题意:质量为i的东西有a[i]个,分两拨问能不能质量相等,质量和为奇显然不能,偶数时只要达到sum/2的背包就行了,剩下的自然组成了另外sum/2的背包。
多重背包:
显然超时了,多重背包分成了好多的1个01背包,然而可以用二进制分,这样需要几个都可以加出来。比如13分成1,2,4,6,需要5个的话拿1,4就行。
然而这种跟poj 2392一样的做法是最快的,一种一种的往里放,在数量和价值的条件下,一点一点加,看能达到的最大高度。
#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
int a[7],f[maxn],num[maxn];
int main(){
int cnt=0;
while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]){
memset(f,0,sizeof(f));
memset(num,0,sizeof(num));
cnt++;
int sum=0,ans=0;;
for(int i=1;i<=6;i++)
sum+=a[i]*i;
if(sum==0) break;
if(sum%2==1){
printf("Collection #%d:\nCan't be divided.\n\n",cnt);
continue;
}
sum/=2;
f[0]=1;
for(int i=1;i<=6;i++){
memset(num,0,sizeof(num));
for(int j=i;j<=sum;j++)
if(!f[j]&&f[j-i]&&num[j-i]+1<=a[i]){
f[j]=1;
num[j]=num[j-i]+1;
ans=max(ans,j);
}
}
if(ans==sum)
printf("Collection #%d:\nCan be divided.\n\n",cnt);
else
printf("Collection #%d:\nCan't be divided.\n\n",cnt);
}
return 0;
}
题意:质量为i的东西有a[i]个,分两拨问能不能质量相等,质量和为奇显然不能,偶数时只要达到sum/2的背包就行了,剩下的自然组成了另外sum/2的背包。
多重背包:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=200005; int a[7],dp[maxn]; int main(){ int cnt=0; while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]){ memset(dp,0,sizeof(dp)); cnt++; int sum=0; for(int i=1;i<=6;i++) sum+=a[i]*i; if(sum==0) break; if(sum%2==1){ printf("Collection #%d:\nCan't be divided.\n",cnt); continue; } sum/=2; for(int i=1;i<=6;i++) for(int j=1;j<=a[i];j++) for(int k=sum;k>=i;k--) dp[k]=max(dp[k],dp[k-i]+i); if(dp[sum]==sum) printf("Collection #%d:\nCan be divided.\n",cnt); else printf("Collection #%d:\nCan't be divided.\n",cnt); } return 0; }
显然超时了,多重背包分成了好多的1个01背包,然而可以用二进制分,这样需要几个都可以加出来。比如13分成1,2,4,6,需要5个的话拿1,4就行。
#include<bits/stdc++.h> using namespace std; const int maxn=200005; int a[7],dp[maxn],w[maxn]; int main(){ int cnt=0; while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]){ memset(dp,0,sizeof(dp)); memset(w,0,sizeof(w)); cnt++; int sum=0; for(int i=1;i<=6;i++) sum+=a[i]*i; if(sum==0) break; if(sum%2==1){ printf("Collection #%d:\nCan't be divided.\n\n",cnt); continue; } sum/=2; int cnt0=1; for(int i=1;i<=6;i++){ for(int j=1;j<=a[i];j<<=1){ w[cnt0++]=j*i; a[i]-=j; } if(a[i]>0) //把最后剩余的那个拆出来 w[cnt0++]=a[i]*i; } for(int i=1;i<=cnt0;i++) for(int j=sum;j>=w[i];j--) dp[j]=max(dp[j-w[i]]+w[i],dp[j]); if(dp[sum]==sum) printf("Collection #%d:\nCan be divided.\n\n",cnt); else printf("Collection #%d:\nCan't be divided.\n\n",cnt); } return 0; }
然而这种跟poj 2392一样的做法是最快的,一种一种的往里放,在数量和价值的条件下,一点一点加,看能达到的最大高度。
#include<bits/stdc++.h>
using namespace std;
const int maxn=200005;
int a[7],f[maxn],num[maxn];
int main(){
int cnt=0;
while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]){
memset(f,0,sizeof(f));
memset(num,0,sizeof(num));
cnt++;
int sum=0,ans=0;;
for(int i=1;i<=6;i++)
sum+=a[i]*i;
if(sum==0) break;
if(sum%2==1){
printf("Collection #%d:\nCan't be divided.\n\n",cnt);
continue;
}
sum/=2;
f[0]=1;
for(int i=1;i<=6;i++){
memset(num,0,sizeof(num));
for(int j=i;j<=sum;j++)
if(!f[j]&&f[j-i]&&num[j-i]+1<=a[i]){
f[j]=1;
num[j]=num[j-i]+1;
ans=max(ans,j);
}
}
if(ans==sum)
printf("Collection #%d:\nCan be divided.\n\n",cnt);
else
printf("Collection #%d:\nCan't be divided.\n\n",cnt);
}
return 0;
}
相关文章推荐
- 【HDU - 1059 Dividing】 混合背包
- HDU1059——Dividing多重背包
- Hdu 1059 Dividing & Zoj 1149 & poj 1014 Dividing(多重背包)
- HDU 1059 Dividing(多重背包)
- Hdu 1059 Dividing (多重背包)
- hdu 1059 Dividing 多重背包
- hdu1059 Dividing 【多重背包】
- hdu1059 Dividing 我的ACM我的梦,回顾篇 完全背包
- HDU 1059 Dividing 多重背包 .
- HDU 1059 Dividing(多重背包)
- 【多重背包】HDU 1059 Dividing
- ACM学习历程—HDU 1059 Dividing(dp && 多重背包)
- Dividing (HDU 1059) —— 多重背包
- hdu 1059 Dividing(多重背包)
- hdu 1059 Dividing(二进制转化优化) 分组背包
- hdu 1059 Dividing--DP-多重背包问题
- hdu1059 Dividing (多重背包) 经典
- HDU 1059 Dividing (多重背包问题)
- HDU1059-Dividing-DP(多重背包)
- HDU 1059 Dividing 多重背包二进制优化