01背包
1.对体积背包
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int t;cin>>t;
while(t--)
{
int n,v;cin>>n>>v;
int w[1005],v1[1005],dp[1005];
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
cin>>w[i];
for(int i=1;i<=n;i++)
cin>>v1[i];
for(int i=1;i<=n;i++)
{
for(int j=v;j>=v1[i];j--)
{
dp[j]=max(dp[j],dp[j-v1[i]]+w[i]);
}
}
for(int i=v;~i;i--)cout<<dp[i]<<endl;
/// dp[v] 为最大价值
}
}
2.对价值背包
#include<iostream>
#include<algorithm>
#include<cstring>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
int dp[5005];
int weight[5005];
int value[5005];
int main()
{
int n,v,t;
cin>>t;
while(t--)
{
cin>>n>>v;
int sum=0;
memset(dp,inf,sizeof(dp));
for(int i=1; i<=n; i++)
{
cin>>value[i];
sum+=value[i];
}
for(int i=1;i<=n;i++)cin>>weight[i];
dp[0]=0;
for(int i=1; i<=n; i++)
{
for(int j=sum;j>=value[i]; j--)
{
dp[j]=min(dp[j],dp[j-value[i]]+weight[i]);
}
}
for(int i=sum;~i;i--)cout<<dp[i]<<endl;/// dp[i]<=v i为最大价值
}
}
___________________________________________________________
sum+=weight[i];
for(1->n;i++)
{
i!=1-->sum-=weight[i];
load=max(v-sum,weight[i]);
for(v->load;j--)
{
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
}
}
___________________________________________________________
for (int i = 0; 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];
if(!mark[j-w[i]])mark[j-w[i]]++;
mark[j]=mark[j-w[i]];
}
else if(dp[j]==dp[j-w[i]]+v[i])
{
if(!mark[j-w[i]])mark[j-w[i]]++;
mark[j]+=mark[j-w[i]];
}
}
} // 01 背包方案数
01背包第k优解
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#define me(a,x) memset(a,x,sizeof(a))
using namespace std;
int dp[1005][35];
signed main()
{
int t;cin>>t;while(t--)
{
int n,v,k;scanf("%d%d%d",&n,&v,&k);
int value[105],weight[105];me(dp,0);
int a[35],b[35];
for(int i=1;i<=n;i++)scanf("%d",value+i);
for(int i=1;i<=n;i++)scanf("%d",weight+i);
for(int i=1;i<=n;i++)
{
for(int j=v;j>=weight[i];j--)
{
for(int t=1;t<=k;t++)
{
a[t]=dp[j][t]; //将过程中得到的解保存到
b[t]=dp[j-weight[i]][t]+value[i]; // a,b 数组中
}
int m=1,x=1,y=1;
a[k+1]=b[k+1]=-1;
while(m<=k and (a[x]!=-1 or b[y]!=-1))
{
if(a[x]>b[y])dp[j][m]=a[x++];// 第m优解保存下来
else dp[j][m]=b[y++];
if(dp[j][m]!=dp[j][m-1])m++; // 去掉重复的解
}
}
}cout<<dp[v][k]<<endl;
}
}
01背包路径
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#define me(a,x) memset(a,x,sizeof(a))
using namespace std;
int dp[1000005];
int path[25][10005];
int main()
{
int N,track;while(cin>>N>>track)
{
int val[track+5],wei[track+5];
me(dp,0);me(path,0);
for(int i=1;i<=track;i++)
{
scanf("%d",wei+i);
val[i]=wei[i];
}
for(int i=1;i<=track;i++)
{
for(int j=N;j>=wei[i];j--)
{
if(dp[j]<dp[j-wei[i]]+val[i])
{
dp[j]=dp[j-wei[i]]+val[i];
path[i][j]=1;
}
else dp[j]=dp[j];
}
}
int i=track,j=N;
while(i>=1&&j>=0)
{
if(path[i][j]){cout<<wei[i]<<" ";j-=wei[i];}i--;
}
cout<<"sum:"<<dp[N]<<endl;
}
}
多重背包
#include<bits/stdc++.h> //多重背包 每件物品 有限件
using namespace std;
#define me(a,x) memset(a,x,sizeof(a))
int main(int argc, char const *argv[])
{
int n,v;cin>>n>>v;
int dp[1005];me(dp,0);
int weight[1005],value[1005],count[10005];
for(int i=0;i<n;i++)cin>>weight[i]>>value[i]>>count[i];
// for(int i=0;i<n;i++) //..........................................1
// {
// for(int j=v;j>=weight[i];j--)
// {
// for(int k=1;k<=count[i];k++)
// {
// if(j>=k*weight[i])
// {
// dp[j]=max(dp[j],dp[j-k*weight[i]]+k*value[i]);
// }
// }
// }
// }cout<<dp[v]<<endl;//...................................常规写法
// for(int i=0;i<n;i++)//.........................................2
// {
// int k;
// for(int k=1;k<count[i];count[i]-=k,k<<=1)
// {
// for(int j=v;j>=k*weight[i];j--)
// {
// dp[j]=max(dp[j],dp[j-k*weight[i]]+k*value[i]);
// }
// }
// for(int j=v;j>=count[i]*weight[i];j--)dp[j]=max(dp[j],dp[j-count[i]*weight[i]]+count[i]*value[i]);
// }cout<<dp[v]<<endl;//......................................二进制优化
// int use[1005];dp[0]=1;//.................................3
// for(int i=0;i<n;i++)
// {
// me(use,0);
// for(int j=weight[i];j<=v;j++)
// {
// if(!dp[j] and dp[j-weight[i]] and use[j-weight[i]]<count[i])
// {
// dp[j]=1;
// use[j]=use[j-weight[i]]+1;
// }
// }
// }
// for(int i=v;i>=0;i--)if(dp[i]){cout<<i<<endl;}//........当价值 和体积一致时 可已用 标记的方法
}
完全背包
//1.完全背包 每件物品 无限件 || 使得背包刚好装满
#include<bits/stdc++.h>
using namespace std;
#define me(a,x) memset(a,x,sizeof(a))
int main(int argc, char const *argv[])
{
int n,v;cin>>n>>v;
int wei[1005],val[1005];
for(int i=0;i<n;i++)cin>>wei[i]>>v[i];
int dp[1005];for(int i=0;i<=v;i++)dp[i]=-2e9+7;dp[0]=0;// 注意跑for初始化
for(int i=0;i<n;i++)
{
for(int j=wei[i];j<=v;j++)
{
dp[j]=max(dp[j],dp[j-wei[i]]+val[i]);
}
}cout<<dp[v]<<endl;
}
// 2.方案数 装满 体积v的方案
int main(int argc, char const *argv[])
{
int n,v;cin>>n>>v;
int wei[1005];
for(int i=0;i<n;i++)cin>>wei[i];
int dp[1005];me(dp,0);dp[0]=1;
for(int i=0;i<n;i++)
for(int j=wei[i];j<=v;j++)
dp[j]+=dp[j-wei[i]];
cout<<dp[v]<<endl;
//若要求不超过件数c
for(int i=0;i<n;i++)
for(int j=wei[i];j<=v;j++)
for(int k=0;k<=c;k++)
if(j>=wei[i] and j>0)dp[j][k]+=dp[j-wei[i]][k-1];
int sum=0;
for(int i=0;i<=v;i++)sum+=dp[v][i];
}
// 3.有限件 装满
int main(int argc, char const *argv[])
{
int n,v;cin>>n>>v;
int wei[1005],count[1005],use[1005];for(int i=0;i<=v;i++)dp[i]=-121323;dp[0]=0;
for(int i=0;i<n;i++)cin>>wei[i]>>count[i];
for(int i=0;i<n;i++)
{
me(use,0);
for(int j=wei[i];j<=v;j++)
{
if(dp[j]<dp[j-wei[i]]+1 and use[j-wei[i]]<count[i])
{
dp[j]=dp[j-wei[i]]+1;
use[j]=use[j-wei[i]]+1;
}
}
}dp[v]<=0?puts("no"):puts("yes");
}
完全背包路径
#include<bits/stdc++.h>
using namespace std;
#define me(a,x) memset(a,x,sizeof(a))
int main(int argc, char const *argv[])
{
int n,v;cin>>n>>v;
int wei[1005],count[1005],use[1005],path[1005];
for(int i=0;i<=v;i++)dp[i]=-121323;dp[0]=0;
me(path,0);path[0]=-1;//退出条件
for(int i=0;i<n;i++)cin>>wei[i]>>count[i];
for(int i=0;i<n;i++)
{
//me(use,0); // 有限件数加标记
for(int j=wei[i];j<=v;j++)
{
if(dp[j]<dp[j-wei[i]]+1 /*and use[j-wei[i]]<count[i]*/) // 有限的件数
{
dp[j]=dp[j-wei[i]]+1;
//use[j]=use[j-wei[i]]+1;
path[j]=j-wei[i];
}
}
}
for(int t=p;path[t]!=-1;t=path[t])cout<<t-path[t]<<endl;
}
©著作权归作者所有:来自51CTO博客作者qinXpeng的原创作品,如需转载,请注明出处,否则将追究法律责任
背包51ctoDP