• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

yongchaoD

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

采药(01背包+滚动数组优化)

题目来源:https://www.luogu.com.cn/problem/P1048
//
题意:01背包板子
//
讲解:二维01背包(b站):【【自制】01背包问题算法动画讲解】https://www.bilibili.com/video/BV1pY4y1J7na?vd_source=edd8d483423d58308aefa72fbec9bd22
//
思路:二维dp:dp[i][j]:表示选择前i种物品,背包容量为j的最优最大价值。
状态转移方程:if(t>=w[i]){ dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]) } else{dp[i][j]=dp[i-1][j]};状态转移方程的由来我就不赘述了,重要的是明白dp的二维表是如何递推的。
//
滚动数组优化:由二维dp可知,每一个都是上一层dp[i-1]可得,滚动数组就是每一次将上一层的dp[i-1][j]的最优解拷贝到dp[i]层。这里注意!!!滚动数组遍历时,容量表里一定是从大到小,你想想,二维dp转移是不是每次都是从头上不选dp[i-1][j]和上一层的前面dp[i-1][j-w[i]],自然一位更新,要后面获取前面的数据,从后面依次向前更新。如果是从小到大,那1号位置更新了,2号位置得到的1号信息更新不是上一层的数据,这样会造成一个物品购买多次。

//
二维dp:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t,m;//t:容量
    cin>>t>>m;
    int dp[109][1009];
    int w[109],v[109];
    for(int i=1;i<=m;i++){
      cin>>w[i]>>v[i];
    }

    for(int i=1;i<=m;i++){
        for(int j=t;j>=0;j--){
            if(j>=w[i]){
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
            }
            else{
                dp[i][j]=dp[i-1][j];
            }
        }
    }
    cout<<dp[m][t]<<endl;
    return 0;
}
// 滚动数组代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int dp[1009];
int w[109],v[109];
int main()
{
    int t,m;//t:容量
    cin>>t>>m;
    for(int i=1;i<=m;i++){
      cin>>w[i]>>v[i];
    }

    for(int i=1;i<=m;i++){//物品
        for(int j=t;j>=0;j--){//背包
            if(j>=w[i]){
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            }
        }
    }
    cout<<dp[t]<<endl;
    return 0;
}

posted on 2024-08-27 09:22  yongchaoD  阅读(35)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3