【洛谷题解】AT_abc415_e 题解

典。

首先一眼二分对吧。

二分出来这个高桥的初始钱数之后,只需要跑一个最简单的 DP 就可以了。

具体来说的话就是定义 \(dp_{i,j}\) 表示当前到了 \((i,j)\) 这个格子,高桥可以拥有的最大剩余钱数是多少。算上捡钱也算上买食物。

然后从 \((i-1,j)\) 或者 \((i,j-1)\) 转移过来就成。转移式很显然,所以不贴了,具体的去代码里看吧。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2e5+5;
const LL INF = 0x3f3f3f3f3f3f3f3f;
LL n,m,l,r,ans,p[2*N];
vector<LL> a[N],dp[N];
bool check(LL num){
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)dp[i][j]=-INF;
    dp[1][1]=num+a[1][1]-p[2];if(dp[1][1]<0)return 0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(i==1&&j==1)continue;
            if(i>1&&dp[i-1][j]>=0)dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i][j]-p[i+j]);
            if(j>1&&dp[i][j-1]>=0)dp[i][j]=max(dp[i][j],dp[i][j-1]+a[i][j]-p[i+j]);
        }
    return (dp[n][m]>=0);
}
int main(){
    cin>>n>>m;for(int i=1;i<=n;i++)a[i].push_back(0);
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int x;cin>>x;a[i].push_back(x);}
    for(int i=2;i<=n+m;i++)cin>>p[i];
    for(int i=1;i<=n;i++)for(int j=0;j<=m;j++)dp[i].push_back(0);
    l=0,r=2e14,ans=2e14;
    while(l<=r){
        LL mid=(l+r)/2;
        if(check(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<"\n";
    return 0;
}
posted @ 2025-07-20 20:09  嘎嘎喵  阅读(30)  评论(0)    收藏  举报