题目链接
题目描述:
弱弱有两个属性a和b,这两个属性初始的时候均为0,每一天他可以通过努力,让a涨1点或b涨1点。
为了激励弱弱努力学习,我们共有n种奖励,第i种奖励有xi,yi,zi三种属性,若a ≥ xi且b ≥ yi,则弱弱在接下来的每一天都可以得到zi的分数。
问m天以后弱弱最多能得到多少分数。
样例输入
2 4
2 1 10
1 2 20
样例输出
50
dp[i][j]表示a值达到xi, b值达到yi,可以获得的奖励的最大值。
很显然
dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] + (x[i + 1] - x[i] - 1) * v[i][j] + v[i + 1][j]);
dp[i][j + 1] = max(dp[i][j + 1], dp[i][j] + (y[j + 1] - y[j] - 1) * v[i][j] + v[i][j + 1]);
其中, v[i][j]是说a达到了x[i], b达到了y[i],接下来每天可以获得的奖励。
v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + t[i][j];
其中t[i][j]为满足x=i,y=j的奖励的总和。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 100;
map<pair<int, int>, int> p;
set<int> sx, sy;
int x[maxn], y[maxn];
ll dp[maxn][maxn], v[maxn][maxn];
int main()
{
int n, m;
int cnt1 = 1, cnt2 = 1;
scanf("%d %d", &n, &m);
for(int i = 0; i < n; i++) {
int tx, ty, tz;
scanf("%d %d %d", &tx, &ty, &tz);
p[pair<int, int>(tx, ty)] += tz;
if(!sx.count(tx)) sx.insert(tx), x[cnt1++] = tx;
if(!sy.count(ty)) sy.insert(ty), y[cnt2++] = ty;
}
sort(x + 1, x + cnt1);
sort(y + 1, y + cnt2);
for(int i = 1; i < cnt1; i++) {
for(int j = 1; j < cnt2; j++) {
if(!p[pair<int, int>(x[i], y[j])]) v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1];
else v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + p[pair<int, int>(x[i], y[j])];
}
}
for(int i = 0; i < cnt1; i++) {
for(int j = 0; j < cnt2; j++) {
dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] + (x[i + 1] - x[i] - 1) * v[i][j] + v[i + 1][j]);
dp[i][j + 1] = max(dp[i][j + 1], dp[i][j] + (y[j + 1] - y[j] - 1) * v[i][j] + v[i][j + 1]);
}
}
ll ans = 0;
for(int i = 1; i < cnt1; i++) {
for(int j = 1; j < cnt2; j++) {
ll t = dp[i][j] + (m - x[i] - y[j]) * v[i][j];
ans = max(ans, t);
}
}
printf("%lld\n", ans);
}