题意:
解法:
先不考虑数据范围:
令d[i][j]为属性a为i,属性b为j能获得的最大分数
令sum[i][j]为属性a为i,属性b为j之后一天能获得的最大分数
显然sum[i][j]可以用前缀和计算
d[i][j]转移方程:d[i][j]=max(d[i-1][j]+sum[i-1][j],d[i][j-1]+sum[i][j-1])+sum[i][j]
然后考虑数据范围:
发现m,x,y很大,但是n,m很小,可以讲下标范围离散化后再进行dp
最后答案为d[i][j]+(m-xx[i]-yy[j])*sum[i][j]中的最大值
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=4e3+5;
struct Node{
int x,y,z;
}a[maxm];
int sum[maxm][maxm];
int d[maxm][maxm];
int xx[maxm],num1;
int yy[maxm],num2;
int n,m;
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y>>a[i].z;
if(a[i].x+a[i].y>m){
i--,n--;
}
xx[++num1]=a[i].x;
yy[++num2]=a[i].y;
}
sort(xx+1,xx+1+num1);
sort(yy+1,yy+1+num2);
num1=unique(xx+1,xx+1+num1)-xx-1;
num2=unique(yy+1,yy+1+num2)-yy-1;
for(int i=1;i<=n;i++){
a[i].x=lower_bound(xx+1,xx+1+num1,a[i].x)-xx;
a[i].y=lower_bound(yy+1,yy+1+num2,a[i].y)-yy;
sum[a[i].x][a[i].y]+=a[i].z;
}
for(int i=1;i<=num1;i++){
for(int j=1;j<=num2;j++){
sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
}
}
int ans=0;
for(int i=1;i<=num1;i++){
for(int j=1;j<=num2;j++){
d[i][j]=max(d[i-1][j]+(xx[i]-xx[i-1]-1)*sum[i-1][j],d[i][j-1]+(yy[j]-yy[j-1]-1)*sum[i][j-1])+sum[i][j];
if(xx[i]+yy[j]<=m){
ans=max(ans,d[i][j]+(m-xx[i]-yy[j])*sum[i][j]);
}
}
}
cout<<ans<<endl;
return 0;
}