转载:http://blog.csdn.net/lyhvoyage/article/details/8545852
初始化问题:
f[V]为所求
1、如果背包要求正好装满则初始化 f[0] = 0, f[1~w] = -INF
2、如果不需要正好装满 f[0~v] = 0
//01背包模板
for(int i=0;i<T-1;i++)//尝试所有物品
for(int j=lft-5;j>=w[i];j--)//放入j体积的背包
dp[j]=max(dp[j],dp[j-w[i]]+w[i]);//所获得的最大价值
//dp[j]实际理解dp[i][j]表示j体积的背包尝试放入第i个物体所能获得的最大价值,
//dp[j-w[i]]实际理解dp[i][j-w[i]]表示j-w[i]体积尝试放入第i个物品所能获得的最大价值
//max(dp[j],dp[j-w[i]]+w[i])表示j体积尝试放入第i+1个物体所能获得的最大价值
//为不放第i+1个物体获得的价值和放入获得的价值的最大值
for(int i=0;i<N;i++)
for(int j=w[i];j<=V;j++)
dp[j]=max(dp[j],dp[j-w[i]]+p[i]);
for(int i=0;i<N;i++){
for(int j=0;j<num[i];j++){
for(int k=V;k>=p[i];k--)
dp[k]=max(dp[k],dp[k-p[i]]+w[i]);
//混合多重背包模板(多重背包二进制优化)
int f[120005];
int v,k;
void ZeroOnePack(int cost,int weight){
for(int i=v;i>=cost;i--)
if(f[i-cost]+weight>f[i]) f[i]=f[i-cost]+weight;
}
void CompletePack(int cost,int weight){
for(int i=cost;i<=v;i++)
if(f[i-cost]+weight>f[i]) f[i]=f[i-cost]+weight;
}
void MultiplePack(int cost ,int weight,int amount){
if(cost*amount>=v) CompletePack(cost,weight);
else{
for(int k=1;k<amount;){
ZeroOnePack(k*cost,k*weight);
amount-=k;
k<<=1;
}
ZeroOnePack(amount*cost,amount*weight);
}
}
01背包输出方案
百度之星:度度熊的午饭时光
#include <iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
int dp[100000];
int v[100000];
bool vis[100][10000];
int w[100000] ;
stack<int> S ;
int main()
{
int M,n;
int cnt ;
scanf("%d" , & cnt ) ;
for(int cas = 1 ; cas<= cnt ;cas ++ ){
while( !S.empty() )
S.pop() ;
scanf("%d%d",& M , &n);
for(int i=1;i<=n;i++){
scanf("%d%d",&v[i] , & w[i]);
}
memset(dp,0,sizeof(dp));
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++){
for(int j=M;j>=w[i];j--){
if(dp[j]<dp[j-w[i]]+v[i]){
dp[j]=dp[j-w[i]]+v[i];
vis[i][j]=true;
}
}
}
int m=M;
for(int i=n;i>=1;i--){
if(vis[i][m]){
S.push( i );
m -= w[i];
}
}
printf("Case #%d:\n" , cas ) ;
printf("%d %d\n" , dp[M] , M - m ) ;
while(S.size() > 1){
printf("%d ",S.top());
S.pop();
}
if( S.size() == 1)
printf("%d\n" , S.top()) ;
}
return 0;
}