浙江理工大学淘汰赛——猫猫与甜品

题目描述
猫猫在实验室吃甜品喽!
猫猫有n个甜品,每个甜品可以给猫猫带来a的快乐值与b的健康值。初始猫猫快乐值和健康值都为0,猫猫不会让自己的健康值为负数,猫猫想知道自己以合理的顺序吃这些甜品(可以不吃完),猫猫的最大快乐值是多少。
输入
第一行一个整数n(1≤n≤500),表示甜品的数量。
接下来n行,每行2个整数ai,bi(1≤i≤n,-100≤ ai,bi≤100),表示第i个甜品的快乐值与健康值。
输出
输出一个整数,表示猫猫的最大快乐值。
样例输入 Copy
6
1 1
-1 -1
-4 4
-5 5
1 -1
4 -4
样例输出 Copy
2
提示
猫猫可以以1,6,4的顺序吃甜品,最后的健康值为0,快乐值为2。

思路:
因为题面中的快乐值和健康值有正数也有负数,其中健康值必须大于0,那么其实我们可以dp两次,根据健康值分开来dp,正数dp一次,负数dp一次,最后根据两者健康值的绝对值相同或负数的健康值的绝对值小于正数的健康值的情况下,两者相加,就可以得到在健康值大于0的情况下的最优值。

点击查看代码
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
vector<pair<int, int>>a, b;
int aa[55000], bb[55000];
int suma , sumb;
struct node
{
    int happy, health;
}s[550];
void funa()
{
    memset(aa, -0x3f3f3f3f, sizeof(aa));//付初值
    aa[0] = 0;//0这个位置特殊处理,这样子可以从0的位置不断递推,如果健康值不能恰好到i,那么就不会更新这个位置(或者即使更新了也很小)
    int i, j;
    for (i = 0; i < a.size(); i++)
    {
        for (j = suma; j >= 0; j--)
        {
            if (j >= a[i].second&&aa[j-a[i].second]+a[i].first>aa[j])
            {
                aa[j] = aa[j - a[i].second] + a[i].first;
            }
        }
    }
}
void funb()
{
    memset(bb, -0x3f3f3f3f, sizeof(bb));
    bb[0] = 0;
    int i, j;
    for (i = 0; i < b.size(); i++)
    {
        for (j = sumb; j >= 0; j--)
        {
            if (j >= b[i].second && bb[j - b[i].second] + b[i].first > bb[j])
            {
                bb[j] = bb[j - b[i].second] + b[i].first;
            }
        }
    }
}
int main()
{
    int n, i, j, k;
    cin >> n;
    for (i = 0; i < n; i++)
    {
        cin >> s[i].happy >> s[i].health;
    }
    for (i = 0; i < n; i++)
    {
        if (s[i].health >= 0)//健康值大于0的情况
        {
            a.push_back({ s[i].happy,s[i].health });
            suma += s[i].health;
        }
        else//小于0的情况
        {
            s[i].health = -s[i].health;
            b.push_back({ s[i].happy,s[i].health });
            sumb += s[i].health;
        }
    }
    funa();
    funb();
    int ans = 0, res = 0;
    for (i = 0; i <= suma; i++)
    {
        res = max(res, bb[min(i, sumb)]);//min(i,sumb)是为了满足b中代表的health值要小于a,两者健康值合起来就会大于0
        ans = max(ans, aa[i] + res);
    }
    cout << ans;
    return 0;
}
posted @   美羊羊给沸羊羊搬砖  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示