目录
题目描述
题目描述
有个背包可承受重量T,现有N件物品,每件物品重量为Wi,价值为Vi ,每件物品的数量是无穷的,这个背包可以装载物品的最大价值是多少?
输入格式
第一行,两个整数,分别表示T和N,用空格隔开(T≤1000,N≤100)
接下来T行,每行两个整数,分别表示N件物品的重量Wi和价值Vi(1≤Wi,Vi≤100)
输出格式
一行,表示这个背包可以装载物品的最大价值
输入输出样列
输入样例1:
100 5
77 92
22 22
29 87
50 46
99 90
代码实现
//完全背包---贪心算法
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n,m;//物品数,最大容量
typedef struct{
int v;//容量
double w;//价值
double one;//单位价值
}P;
P p[N];
bool cmp(P a,P b){
return a.one>b.one;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>p[i].v>>p[i].w;
p[i].one=1.0*p[i].w/p[i].v;
}
sort(p+1,p+1+n,cmp);//单价降序排序
double val=0;
for(int i=1;i<=n;i++){
if(p[i].v<=m){
val+=p[i].w;
m-=p[i].v;
}else{
val+=m*p[i].one;
break;
}
}
cout<<"最大价值为:"<<val<<endl;
return 0;
}
运行结果
思路
完全背包和0-1背包的区别:“物品数量不是1 1个,而是无穷多个”。
那么:
对于物品i来说,最多能装多少个在背包里呢?
背包容量为C,最多能装C/w[i]个物品i。
多重背包:
将多重背包中的s[i]定义为C/w[i]进行求解。
过程:
1 定义状态: d(i,j)表示前i种物品放在承重量为j的背包里可以获得的最大价值。
2 状态转移方程:
dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);
3 时间复杂度
O(N*C*K)
01-背包:
将每种完全背包物品拆成C/w[i]件物品进行0-1背包的DP。
完全背包算法:
定义状态:d (i, j)表示为前i种物品分配j的背包空间,可以获得的最大价值!
建立d(N,C)的表,DP将进行填表操作。
状态转移方程:对于物品i的决策可以分为两大类:
第i件物品一件也不放:d(i,j)=d(i-1,j)上一行。
第i种物品至少放一个:
由于至少放入一个,考虑最后一个放入的i物品,其占用w_i的空间,并带来v_i的价值。
由于物品i有无限多个,放入一个以后还是有无限多个,但是背包大小减少了w_i。
问题转换为从前i个物品种选择一些物品放入j-w_i的背包中可以获得的最大价值。
状态转移方程:dp(i,j)=max(dp(i-1,j),d(i,j-w_i)+v_i)