Problem E. Growth
题解:
艰难的补题中...题目中m,x,y都很大,但是n只有1000,所以就将x,y离散化(因为递增可以算是跨越式的);把奖励的x拿出来从小到大排序,得到。把奖励的y拿出来从小到大排序,得到。
用表示 a 值到达,b 值达到时接下来每天可以得到的奖励。
其中为满足( , )的可得到奖励的总和,反过来就是找最小的大于等于原先的(,)的( , )。
用表示 a 值达到,b 值达到时已经拿到的奖励的最大值。
状态转移方程:
最后统计一下答案就可以了。
代码:
/*
*2018/8/15 ccpc camp day1 E Growth
*Growth:
*把奖励的x拿出来从小到大排序,得到x1,x2,...,xn。
*把奖励的y拿出来从小到大排序,得到y1,y2,...,yn。
*用v[i][j]表示a值到达xi,b值达到yi时接下来每天可以得到的奖励。
*v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + t[i][j];
*其中t[i][j]为满足xi,yj的可能得到奖励的总和, 就是小于等于(xi, yi)。
*用f[i][j]表示a值达到xi,b值达到yj时已经拿到的奖励的最大值。
*f[i-1][j] + (x[i] - x[i-1] - 1) * v[i-1][j] + v[i][j] -> f[i][j]
*f[i][j-1] + (y[j] - y[j-1] - 1) * v[i][j-1] + v[i][j] -> f[i][j]
*最后统计一下答案就可以了。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#define ll long long
using namespace std;
const int maxn = 1e3+7;
int numa, numb;
ll n, m, dp[maxn][maxn], v[maxn][maxn], x[maxn], y[maxn], z[maxn], a[maxn], b[maxn];
set<ll> st;
void init()
{
memset(dp, 0, sizeof(dp));
memset(v, 0, sizeof(v));
numa = 0; numb = 0;
st.clear();
}
int main() {
while(scanf("%lld%lld", &n,&m) != EOF)
{
init();
for(int i = 1; i <= n; i++) scanf("%lld%lld%lld", &x[i], &y[i], &z[i]);
for(int i = 1; i <= n; i++)
if(st.count(x[i]) == 0) {
a[++numa] = x[i];
st.insert(x[i]);
}
st.clear();
for(int i = 1; i <= n; i++)
if(st.count(y[i]) == 0) {
b[++numb] = y[i];
st.insert(y[i]);
}
sort(a + 1, a + numa + 1);
sort(b + 1, b + numb + 1);
for(int i = 1; i <= n; i++) {
int v1 = lower_bound(a + 1, a + 1 + numa, x[i]) - a;
int v2 = lower_bound(b + 1, b + 1 + numb, y[i]) - b;
v[v1][v2] += z[i];
}
for(int i = 1; i <= numa; i++)
for(int j = 1; j <= numb; j++)
v[i][j] += (v[i-1][j] + v[i][j-1] - v[i-1][j-1]);
for(int i = 1; i <= numa; i++)
for(int j = 1; j <= numb; j++)
dp[i][j] = max(dp[i-1][j] + (a[i] - a[i-1] - 1)*v[i-1][j], dp[i][j-1] + (b[j] - b[j-1] - 1)*v[i][j-1]) + v[i][j];
ll ans = 0;
for(int i = 1; i <= numa; i++)
for(int j = 1; j <= numb; j++)
if(a[i] + b[j] <= m) ans = max(ans, dp[i][j] + v[i][j]*(m - a[i] - b[j]));
printf("%lld\n", ans);
}
return 0;
}