【dp+优化】tyvj1013 FAreStorm教你找GF

http://tyvj.cn/p/1013
题目大意:有n个MM等着被约,约第i个MM需要人民币rmb(i)元以及人品rp(i),还要耗费时间time(i),要求在人品和人民币消耗在一定范围内,get尽可能多的MM并且时间最少的方案。

这个题一眼就看得出是DP,但是比较坑的是这个题的状态维度很多,时间、金钱、人品,连MM数量都要考虑= =

标准的DP算法很容易想出来,dp[i][j][k][l]代表已经约了i个MM,花费j人品,k人民币且攻略了l个MM所耗费的最少时间,然而这样超时先不说,内存会炸掉的= =

于是我们换种方法考虑:时间越少越好,那么可不可以把时间看做一项损失?MM越多越好,可不可以把MM看做一种收益?于是我们把攻略l个MM耗费t时间变成一个压进一个维度,这个维度中的值又怎么计算呢?既然MM是收益,时间是损失,且以MM为主,那么我们就把MM的价值设的非常大,把时间看做损失,于是得到一个公式:

收益=MM数x一个有趣的值-时间x另一个有趣的值
这两个有趣的值要满足什么呢?
需要满足的是:一个MM的收益比泡100个MM花费时间造成的损失更高
听起来很233然而的确是对的,只有这样才能使得一个MM比100000时间更重要
于是最终算法确定:
dp[i][j][k]代表已经约了i个MM,花费j人品,k人民币获得的最大收益,状态转移方程式嘛……这样应该很简单了233

#include <iostream>
#include <cstdio>
using namespace std;
int a[101][201][201];
int rmb[101];
int rp[101];
int time[101];
int m,r;
int main()
{
    int n;
    cin >> n;
    for(int i = 1;i <= n;i ++)
    {
        cin >> rmb[i] >> rp[i] >> time[i];
    }
    cin >> m >> r;
    int maxn = 0;
    for(int i = 1;i <= n;i ++)
    {
        for(int j = 0;j <= m;j ++)
        {
            for(int k = 0;k <= r;k ++)
            {
                a[i][j][k] = max(a[i][j][k],a[i-1][j][k]);
                a[i][j+rmb[i]][k+rp[i]] = max(a[i][j+rmb[i]][k+rp[i]],a[i-1][j][k]+200000-time[i]);
                maxn = max(maxn,a[i][j][k]);
            }
        }
    }
    while(maxn > 0)
    {
        maxn -= 200000;
    }
    cout << -maxn << endl;
    fclose(stdin);
    fclose(stdout);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值