传送门:牛客
题目描述:
题目较长此处省略
输入:
1 1 74
2
1 502 47
输出:
408
自我感觉这道题还是挺难处理的(虽然代码不长,但是毕竟四星),经过了这道题感觉自己对于 01 背包 01背包 01背包的理解更上一层楼了
主要思路:
- 感觉每一个人首先看到这道题肯定都会想到01背包,但是感觉直接套又有点问题.首先我们会发现我们的价值是会随着我们的时间改变的,所以假设我们直接套01背包的代码的话就会发现我们的 d p [ t ] dp[t] dp[t]显然不是最优的,因为我们当前的物品放的越早我们的价值就是越高的.但是这个问题也不难解决,只要枚举一遍我们的时间即可
- 其次,因为我们的题目中要求的是至少有一个菜肴,并且我们的价值是可以为负的,所以我们应该将我们的dp数组全部赋值为-inf,然后将我们的 d p [ 0 ] = 0 dp[0]=0 dp[0]=0,这样的话就可以保证我们至少应该有一个菜肴会被选进来
- 当我们想完前两点之后我们这个代码其实还是有bug的,因为我们的菜肴是与我们的时间有关的,也就是说假设我们从 1 菜肴转移到我们的 2 菜肴 1菜肴转移到我们的2菜肴 1菜肴转移到我们的2菜肴与我们 2 菜肴转移到 1 菜肴 2菜肴转移到1菜肴 2菜肴转移到1菜肴,这两个转移最终的答案肯定是不一样的,但是我们在上述的背包里并没有考虑这一点.所以我们需要考虑这一点.也就是尽量的让更加优的菜肴先放在前面,也就是先进背包
- 对于两个物体 A, B, 先取 A 物体比先取 B 物体优
当且仅当
a i − b i ∗ c i + a j − b j ∗ ( c i + c j ) a_i -b_i * c_i + a_j - b_j * (c_i + c_j) ai−bi∗ci+aj−bj∗(ci+cj) > > > a j − b j ∗ c j + a i − b i ∗ ( c i + c j ) a_j - b_j * c_j + a_i - b_i * (c_i +c_j) aj−bj∗cj+ai−bi∗(ci+cj)
化解一下就是
b
j
∗
c
i
<
b
i
∗
c
j
b_j * c_i < b_i * c_j
bj∗ci<bi∗cj
然后我们直接根据上述sort一下即可
下面是具体的代码部分:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
#include <deque>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x = 0, w = 1;
char ch = getchar();
for (; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') w = -1;
for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x * w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps = 1e-8;
int n, m, t;
ll dp[1000010];int b[maxn];
struct Food{
int j,a,c;
}food[maxn];
bool cmp(Food aa,Food bb) {
return b[aa.j]*bb.c>b[bb.j]*aa.c;
}
int main() {
n = read();
m = read();
t = read();
for (int i = 1; i <= n; i++) b[i]=read();
for (int i = 1; i <= m; i++) {
food[i].j=read();food[i].a=read();food[i].c=read();
}
sort(food+1,food+1+m,cmp);
ll ans=-ll_maxn;
memset(dp,-0x3f,sizeof(dp));
dp[0]=0;
for (int k = 1; k <= m; k++) {
for (int i = t; i >= food[k].c; i--) {
dp[i] = max(dp[i], dp[i - food[k].c] + food[k].a - i * b[food[k].j]);
ans=max(ans,dp[i]);
}
}
cout << ans << endl;
return 0;
}