【题目描述】
设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。
【输入】
第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30);
第2…N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。
【输出】
仅一行,一个数,表示最大总价值。
【输入样例】
10 4
2 1
3 3
4 5
7 9
【输出样例】
max=12
【来源】
No
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
const int maxn = 205;
using namespace std;
int w[maxn],c[maxn],dp[maxn];
int main(){
int V,N;
cin>>V>>N;
for(int i=1;i<=N;i++) cin>>w[i]>>c[i];
for(int i=1;i<=N;i++){
for(int v=w[i];v<=V;v++){
dp[v] = max(dp[v] , dp[v-w[i]] + c[i]);
}
}
cout<<"max="<<dp[V];
return 0;
}
完全背包模板题,和01背包的却别就是一个是顺序取,一个是逆序取。
比如取第i个物品时
01背包是每一样只能取一个,所以取的时候考虑的是i-1的情况
完全背包是每一样都能无限取,所以考虑的i的情况
这两种不同的考虑就决定你滚动数组的取值顺序
01背包
1.dp[i-1][v] 不取i
2.dp[i-1][v-w[i]]+c[i] 取i
因为v > v-w[i] 你考虑的是i-1的情况,所以i-1前面的值是一定不能变的,简单点说i的情况只和i的正上方和左上方有关(i-1),因为是一维数组,后面的不影响前面的,后面更新的是i的情况
完全背包
1.dp[i-1][v] 不取i
2.dp[i][v-w[i]]+c[i] 取i
和01差不都,关键是取i的时候不一样,因为转换到一直取i的情况,而i的情况只和正上方和他自己这行的左边有关,你只有先把自己的左边求了才能从左往右求,
我这没有图片,算法笔记P446页有,图片一目了然
总之,01背包是根据i-1行的左侧从右向左把i-1跟新成i
完全背包则是根据自己的这一行从左往右生成i的 ( 正上方的i-1)