题目
试题描述
|
经典的 0-1 背包:知道 n 个物品的体积和价值,第 i 个体积为 V[i],价值为 W[i],有一个背包的容积为 C。求在体积不超容积的前提下,背包中可装物品价值的最大值。 |
输入
|
第一行:两个整数 n 和 C ;
第 2 行到第 n+1 行:每行两个整数 Vi 与 Wi,有一个空格分隔。 |
输出
|
一个数,表示背包中能得到物品价值的最大值。
|
输入示例
|
2 10
1 1 2 2 |
输出示例
|
3
|
其他说明
|
数据范围:输入的数据均不超过20,经典的dp。
|
分析
这是经典的01背包问题,最基础的动态规划。noip考了不下5次。
所谓动态规划就是是通过组合子问题的解来求解原问题的。而类似递推(不会递推看:https://www.cnblogs.com/zxjhaha/p/11295080.html),动态规划有一个转移方程。通过已知转移未知。所以关键在于求出转移方程。让我们来看看这道题。
首先,定义一个dp数组,dp[i][j]表示前i个物品剩余体积为j的最大价值。我们所以要面临的就是取与不去的问题。转移方程如下。
注:c数组表示物体重量,v数组表示价值。
完整代码如下。
#include <bits/stdc++.h> using namespace std; int n,m,dp[10005][10005],c[25],v[25]; int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>c[i]>>v[i]; for(int i=1;i<=n;i++) { for(int j=0;j<=m;j++) //枚举从0到m { if(j>=c[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+v[i]); //如果放得下,就带入转移方程。 else dp[i][j]=dp[i- 1][j]; //不放的情况 } } cout<<dp[n][m]; //输出前n个物品剩余体积为m的最大价值。 return 0; }