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);
}