2023牛客暑期多校训练营5-H Nazrin the Greeeeeedy Mouse

本文讲述了如何使用01背包的动态规划方法解决2023牛客暑期多校训练营中的HNazrintheGreeeeeedyMouse问题,通过分析题目特点,提出针对单调递增背包容量优化的解题策略,以及计算dp状态转移的详细步骤和C++代码实现。
摘要由CSDN通过智能技术生成

2023牛客暑期多校训练营5-H Nazrin the Greeeeeedy Mouse

biubiu~

题目描述

在这里插入图片描述

解题思路

仅看题目,我们可以想到01背包,但是仔细一看,dp可能会包含多个需要维护的值,跑01很显然会炸。
我们仔细看题目,会发现这个背包容量sz[i]是单调递增的,而m的范围是[1,1e5] 为了缩短时间,我们可以只取最后200个包。此时我们的时间是O( n 3 n^3 n3)
先处理出 [ l , r ] [l,r] [l,r]区间内用 s s s 能获得的最大芝士重量
f i , j , s = m a x ( f i , j − 1 , s − a j + b j , f i , j − 1 , s ) f_{i,j,s}=max(f_{i,j-1,s-a_j}+b_j,f_{i,j-1,s}) fi,j,s=max(fi,j1,saj+bj,fi,j1,s)
可以设dp的状态为走的步数当前位置
转移方程式为: d p i , j = m a x ( d p i − 1 , y + f y + 1 , j , s z i , d p i , j ) dp_{i,j}=max(dp_{i-1,y}+f_{y+1,j,sz_i},dp_{i,j}) dpi,j=max(dpi1,y+fy+1,j,szi,dpi,j)
其中的y表示从y走到x,枚举y从1到x 再在循环中统计dp最大值

代码

#include <bits/stdc++.h>
using namespace  std;
const int N=1e5+2;
const int M=2e2+2;
int n,m;
int dp[M][M];
int f[M][M][M];
int a[M],b[M];
int pos[M];
int main()
{
    scanf("%d%d",&n,&m);    
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
    int x,cnt=0;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&x);
        if(i+n>=m) pos[++cnt]=x;//只记录最后n个包
    }
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        {
            for(int s=a[j];s<=200;s++)
                    f[i][j][s]=max(f[i][j-1][s-a[j]]+b[j],f[i][j-1][s]);
            for(int s=0;s<=200;s++)//比较是否跳过该芝士的最优解
                    f[i][j][s]=max(f[i][j-1][s],f[i][j][s]);
        }
    int l,r,s;
//     while(cin>>l>>r>>s)
//     {
//     	cout<<f[l][r][s]<<" \n";
// 	}
    int ans=0;
    for(int i=1;i<=cnt;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int y=0;y<=j;y++)
            {
                dp[i][j]=max(dp[i-1][y]+f[y+1][j][pos[i]],dp[i][j]);
                ans=max(ans,dp[i][j]);
            }
        }
    }
    printf("%d",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值