闫氏DP分析法

文章讲述了如何使用动态规划方法解决一个经典的背包问题,即在不超过背包容量的前提下,选择物品以使总价值最大化。通过定义状态和递推公式,给出两种不同优化的C++代码实现,最后推荐在ACwing学习更多算法。
摘要由CSDN通过智能技术生成

题干:N 个物品,每个物品有对应的价值和体积,背包容量为 V,如何选择物品使得在不超过背包容量的前提下,价值之和最大。
每个物品都可以选和不选,两种选择,那么一共有 2 N 2^N 2N 两种方案,所以题目是一个有限集合的最值问题,所以可以用 y 氏 DP 法来分析

步骤一:状态表示

f ( i , j ) f(i,j) f(i,j)

  • 确定集合:(i 和 j 表示的意思)在只考虑前 i 个物品,并且物品总体积不超过 j 的选法的集合
  • 属性:( f ( i , j ) f(i,j) f(i,j) 的值代表的意思,和题意相关)当前集合中的最大价值
  • image.png

步骤二:状态计算

  • 那么 f ( i , j ) f(i,j) f(i,j) 如何计算呢,对于上述的集合,我们可以分为两个子集
    • 一个子集是没有选择物品 i 的集合
      • 如果不选择物品 i,那么我们只需要找到只考虑前 i − 1 i-1 i1 个物品,并且物品总体积不超过 j 的选法集合中的最大价值,也就是 f ( i − 1 , j ) f(i-1,j) f(i1,j)
    • 一个子集是选择了物品 i 的集合
      • 如果选择了物品 i,那么我们只需要找到只考虑前 i − 1 i-1 i1 个物品,并且物品总体积不超过 j − v [ i ] j-v[i] jv[i] 的选法集合中的最大价值,也就是 f ( i − 1 , j − v [ i ] ) f(i-1,j-v[i]) f(i1,jv[i])
      • 然后加上物品 i 的价值 w [ i ] w [i] w[i] f ( i − 1 , j − v [ i ] ) + w [ i ] f(i-1,j-v[i])+w[i] f(i1,jv[i])+w[i]
      • 注意 j 和 v[i]的大小

板子

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1005;

int n,v;
int V[N],W[N];
int dp[N][N];

int main(){
    cin>>n>>v;
    for(int i=1;i<=n;i++) cin>>V[i]>>W[i];
    
    for(int i=1;i<=n;i++){
        for(int j=0;j<=v;j++){
            dp[i][j]=dp[i-1][j];
            if(j>=V[i]) dp[i][j]=max(dp[i][j],dp[i-1][j-V[i]]+W[i]);
        }
    }
    cout<<dp[n][v];
    return 0;
}

优化

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1005;
int n,v;
int V[N],W[N];
int dp[N];
int main(){
    cin>>n>>v;
    for(int i=1;i<=n;i++) cin>>V[i]>>W[i];
    for(int i=1;i<=n;i++)
        for(int j=v;j>=V[i];j--)
            dp[j]=max(dp[j],dp[j-V[i]]+W[i]);
    cout<<dp[v];
    return 0;
}

最后推荐大家去acwing上学算法!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值