5873. 小p的屬性
阿新 • • 發佈:2018-12-11
題目大意:
思路:
把問題轉化一下,就是在一個二維的平面上,有些點有權值,你每次都可以向右或者向上走,經過一個點後得到他的權值,並且每走一步都會再次加上他的權值,問你走k步的最大權值是多少,k=10e9。 我們發現他每次走都會走到某個點上,這樣答案才會更優,所以我們把所有點的橫座標縱座標拿出來離散,然後插入點值,這樣就可以不用列舉座標了。先預處理字首和!
程式:
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #define N 2005 #define LL long long using namespace std; struct data{LL x,y,z;}x[N]; LL sum[N][N],f[N][N],b[N]; LL n,m,size,cnt; int main(){ freopen("growth.in","r",stdin); freopen("growth.out","w",stdout); scanf("%lld%lld",&n,&m); for (int i=1;i<=n;i++) { scanf("%lld%lld%lld",&x[i].x,&x[i].y,&x[i].z); } for (int i=1;i<=n;i++) b[++cnt]=x[i].x,b[++cnt]=x[i].y; sort(b+1,b+cnt+1); size=unique(b+1,b+cnt+1)-b-1; for (int i=1;i<=n;i++){ x[i].x=lower_bound(b+1,b+size+1,x[i].x)-b; x[i].y=lower_bound(b+1,b+size+1,x[i].y)-b; sum[x[i].x][x[i].y]+=x[i].z; } for (int i=1;i<=size;i++) for (int j=1;j<=size;j++){ sum[i][j]=sum[i-1][j]+sum[i][j-1]+sum[i][j]-sum[i-1][j-1]; } for (int i=1;i<=size;i++) for (int j=1;j<=size;j++){ if (i==1&&j==1) continue; f[i][j]=max(f[i-1][j]+sum[i-1][j]*(b[i]-b[i-1]-1),f[i][j-1]+sum[i][j-1]*(b[j]-b[j-1]-1))+sum[i][j]; } LL ans=0; for (int i=1;i<=size;i++) for (int j=1;j<=size;j++) if (b[i]+b[j]<=m){ ans=max(ans,f[i][j]+sum[i][j]*(m-b[i]-b[j])); } printf("%lld\n",ans); }