背包问题
1. 01背包
为题描述:s件物品, 背包容量为 m ,给出每件物品的cost,与 value 求在背包容量内最大的价值是多少?
void pack_01(int weight,int value) { for(int i=背包容量;i>=weight;i--) dp[i]=max(dp[i],dp[i-weight]+value); } int DP() { for(int i=0;i<物品件数;i++) pack_01(weight[i],value[i]); return dp[背包容量]; }
2.完全背包
物品件数为正无穷的背包
scanf("%d",&n); for(i=0; i<n; i++) { scanf("%d%d",&p,&w); for(j=w; j<=m; j++) //与01背包相比倒过来 { dp[j]=max(dp[j],dp[j-w]+p); // dp[i] 表示i容量的背包最多装的价值。 } }
3.多重背包
int v[10],dp[MM]; int sum; void pack01(int weight,int val) { int i; for(i=sum; i>=weight; i--) dp[i]=max(dp[i],dp[i-weight]+val); } void packcomplete(int weight,int val) { int i; for(i=weight; i<=sum; i++) dp[i]=max(dp[i],dp[i-weight]+val); } void packmul(int weight,int val,int coutt) { if(weight*coutt>=sum) { packcomplete(weight,val); return ; } int k=1,tot=0;; while(k<coutt) //二进制优化 { pack01(k*weight,k*val); coutt-=k; k=k*2; } pack01(coutt*weight,coutt*val); } void DP() { int i; for(i=0; i<=sum; i++) dp[i]=-INF; dp[0]=0; for(i=1; i<=6; i++) { packmul(i,i,v[i]); } }
杭电题目 题目链接>点这里打开<
AC代码
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<string.h> #include<stack> #include<queue> #include<vector> #include<stdlib.h> #include<map> using namespace std; const int INF=10000000; const int MM=60005; int v[10],dp[MM]; int sum; void pack01(int weight,int val) { int i; for(i=sum; i>=weight; i--) dp[i]=max(dp[i],dp[i-weight]+val); } void packcomplete(int weight,int val) { int i; for(i=weight; i<=sum; i++) dp[i]=max(dp[i],dp[i-weight]+val); } void packmul(int weight,int val,int coutt) { if(weight*coutt>=sum) { packcomplete(weight,val); return ; } int k=1,tot=0;; while(k<coutt) { pack01(k*weight,k*val); coutt-=k; k=k*2; } pack01(coutt*weight,coutt*val); } void DP() { int i; for(i=0; i<=sum; i++) dp[i]=-INF; dp[0]=0; for(i=1; i<=6; i++) { packmul(i,i,v[i]); } } int main() { int ncase=0; while(1) { int i; ncase++; sum=0; for(i=1; i<=6; i++) { cin>>v[i]; sum+=i*v[i]; } if(!sum) break; //如果全是0 程序结束 printf("Collection #%d:\n",ncase); if(sum%2==1) //总和为奇数个数则不可能评分 { printf("Can't be divided.\n\n"); continue; } sum=sum/2; //背包容量减半 DP(); if(dp[sum]>=0) printf("Can be divided.\n\n"); else printf("Can't be divided.\n\n"); } return 0; }