At364 E.Maximum Glutton

E.Maximum Glutton


原题链接

题意简述

有n道菜,每道菜有两种属性,酸度和甜度,现要求尽可能多的吃菜,当当前酸度超过最大承受酸度x或当前甜度超过最大承受甜度时不在能够吃菜。当n最大取80,x,y最大取10000的时候最多可以吃的菜数量

解题思路

直接来看考虑二维费用dp,定义状态在枚举到第i个状态下产生j的甜度和k的酸度最大吃的菜的数量
酸度数组记作a,甜度数组记作b,则我们有\(f[i][j][k]=min(f[i][j][k],f[i-1][j-a[i]][k-b[i]]+1)\),简单分析一下发现时空复杂度高达\(O(n·x·y)\),1s肯定跑不了80亿,考虑优化,交换一维酸度和当前吃的菜的数量,我们定义在枚举i个状态,吃了j判菜,产生k的甜度下最大的酸度,那么我们有\(f[i][j][k]=min(f[i-1][j][k],f[i-1][j-1][k-a[i]]+b[i])\)

AC code

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int n,x,y;cin>>n>>x>>y;
    vector<int>a(n+1),b(n+1);
    vector f(n+1,vector<vector<ll> >(n+1,vector<ll>(x+1,INT_MAX)));
    for(int i=0;i<=n;i++) f[i][0][0]=0;
    for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            for(int k=0;k<=x;k++){
                if(k>=a[i]) f[i][j][k]=min(f[i][j][k],f[i-1][j-1][k-a[i]]+b[i]);
                f[i][j][k]=min(f[i][j][k],f[i-1][j][k]);
            }
        }
    }
    ll ans=0;
    for(int i=0;i<=n;i++){
        for(int j=0;j<=x;j++){
            if(f[n][i][j]<=y) ans=max(ans,1LL*min(i+1,n));
        }
    }
    cout<<ans<<endl;
    return 0;
}
posted @ 2025-05-19 20:21  usedchang  阅读(7)  评论(0)    收藏  举报