描述
一个小偷进入超市,带一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是blablaba,求背包最大价值
输入
第一行:两个整数,M(背包容量, M ≤ 200 M≤200 M≤200)和N(物品数量,N≤30);
第2到N+1行:每行二个整数,表示每个物品的重量和价值。
输出
仅一行,一个数,表示最大总价值。
代码如下所示,可参考注释加以理解
#include<iostream>
using namespace std;
int w[100000];
//输入用的两个数组
int v[100000];
//w数组用作记录重量,v记录价值
int f[1000][1000];
//二维数组f含义是放X个物品,重X,内部保存总价值
int main()
{
int m,n;
//定义物品数量n,包最大容量m
cin>>m>>n;
// 给这两个变量赋值(输入)
for(int i=1;i<=n;i++)
//用数组下标习惯上从一开始
{ // 因为用0很容易越界,出现问题
cin>>w[i]>>v[i];
//for循环输入每样物品的重量和价值
}
for(int i=1;i<=n;i++)
{//次数==物品数,对每个物品处理
for(int j=0;j<=m;j++)
{//从零开始遍历背包物品的总重量(m)
f[i][j]=f[i-1][j];
//f[i][j]初始值设置为放新东西之前的价值 (准备背包)
if(j>=w[i])
//判断包里剩余的空间够不够
{
//执行到括号内表示空间足够
if(f[i][j]<f[i-1][j-w[i]]+v[i])
//判断放入第i物品后价值是否比原来大
//不等式前一截表示放入i物品前的总价值
//后一截表示放入后的价值
f[i][j]=f[i-1][j-w[i]]+v[i];
// 如果价值更大,就要放进来
}
}
}
cout<<f[n][m];//输出最大价值
}
一个小偷有一个最多能装 M 公斤的背包,现在有 n 种物品,它们的重量分别是blablabla,价值分别是blablabla,如果每种物品都可以取任意件,求小偷能获得最大总价值。
分析来看,这题与01背包不同,01背包模型为要么有要么无,但这个多了对数量的分析。但是和01背包的差别不大,再加一个用来判断数量的for循环就可以了。
代码如下:(’ ~ ')↓↓↓↓
#include <bits/stdc++.h>
using namespace std;
int m,n;
int dp[1010][1010];
int w[1000000];//weight
int v[1000000];//value
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int k=0;k*w[i]<=j;k++)
{
dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);
}
}
}
cout<<dp[n][m];
}
有N种物品和一个容量是V的背包。
第 i种物品最多有 Si件,每件体积是vi,价值是wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,V用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值.
分析来看,三种背包问题基本架构相似,多重背包是完全背包的更进一步外延,并且看上去差别不大。学习动态规划没有可背的代码,需要我们多敲代码,做到能理解每一句,背写,并且成功运行,在一次次练习中渐渐才有创新的能力。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2000;
int w[MAXN], v[MAXN],s[MAXN], f[MAXN];
int main()
{
int n,m;
cin >> n >> m;
for(int i = 1; i <= n; ++i)
cin >> w[i] >> v[i] >> s[i];
for(int i = 1; i <= n; ++i)
for(int j = m; j>=0; --j)
for(int k = 1; k <= s[i]; ++k)
if(j>=k*w[i])
f[j] = max(f[j], f[j-k*w[i]]+k*v[i]);
cout << f[m] << endl;
return 0;
}
DP算法虽然有些许难懂复杂,高大上的感觉,但是它最大的问题是他的时间复杂度过高,因此无论是在奥赛中还是工程中都对数据规模有限制,但是DP可以被优化,减小他的时间复杂度和空间复杂度,就是让它不费多余的数组,不费更多的时间。
对多重背包问题的二进制优化代码如下:
#include <iostream>
using namespace std;
const int N=10010, V=2010;
int dp[V], v[N], w[N];
int main(){
int n, m, k=0;
cin>>n>>m;
for(int i=1;i<=n;i++){
int vx,wx,s;
cin>>vx>>wx>>s;
for(int j=1;j<=s;j=j*2){
v[++k]=j*vx;
w[k]=j*wx;
s-=j;
}
if(s>0){
v[++k]=s*vx;
w[k]=s*wx;
}
}
n=k;
for(int i=1;i<=n;i++){
for(int j=m;j>=v[i];j--){
dp[j]=max(dp[j], dp[j-v[i]]+w[i]);
}
}
cout<<dp[m];
}
文章结束,这里提供一些资源:
1.网址好记的在线编辑各种语言的网站:
dooccn.com
让您随时随地,在同学面前想装X就装!
2.由NOIP金牌得主开发的代码网站(强烈推荐!!!!):
acwing.com
支持限时编程挑战,天梯匹配在线代码对战,以及奥赛刷题,并且有无数题解+视频+课程
3.