Growth(後續效益持續作用,離散化dp)
阿新 • • 發佈:2020-09-09
題:https://ac.nowcoder.com/acm/problem/19809
題意:倆個屬性ai,bi,每天可以選擇任選一個屬性加1,有n件物品屬性:xi,yi,zi,當屬性ai>=xi&&bi>=yi,在接下來的每天中都會獲得zi的收益,問在m天中最多能收益多少(m<=2e8,xi,y1<=1e8,n<=1e3)
分析:
- 先離散化;
- 定義dp[i][j] 為屬性ai到達i,bj到達 j 時能夠獲得的最大代價;
- 定義val[i][j]為屬性ai到達i,bj到達 j 時能夠獲得的代價和(記1天的代價);
- 那麼dp[i][j]可以由dp[i-1][j], dp[i][j-1]轉化來,前者相差X[i]-X[i-1]-1天,也就是得到了(X[i]-X[i-1]-1)倍dp[i][j-1]的效益,同時加上一倍的val [i][j],後者也同理;
- 最後更新答案,後面的m-X[i]-Y[j]有得“白嫖”;
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define pb push_back const int inf=0x3f3f3f3f; const ll INF=(1ll<<40); const int M=1e3+6; struct node{ ll x,y,z; }a[M]; ll val[M][M],dp[M][M]; ll X[M],Y[M]; int tot; int main(){View Codeint n; ll m; scanf("%d%lld",&n,&m); for(int i=1;i<=n;i++){ ll x,y,z; scanf("%lld%lld%lld",&x,&y,&z); if(x+y>m) continue; a[++tot].x=x; a[tot].y=y; a[tot].z=z; X[tot]=x; Y[tot]=y; } sort(X+1,X+1+tot); int totA=unique(X+1,X+1+tot)-X-1; sort(Y+1,Y+1+tot); int totB=unique(Y+1,Y+1+tot)-Y-1; for(int i=1;i<=n;i++){ int pos1=lower_bound(X+1,X+1+totA,a[i].x)-X; int pos2=lower_bound(Y+1,Y+1+totB,a[i].y)-Y; val[pos1][pos2]+=a[i].z; } for(int i=1;i<=totA;i++) for(int j=1;j<=totB;j++) val[i][j]+=val[i-1][j]+val[i][j-1]-val[i-1][j-1]; for(int i=1;i<=totA;i++) for(int j=1;j<=totB;j++){ dp[i][j]=val[i][j]+max(dp[i-1][j]+(X[i]-X[i-1]-1)*val[i-1][j],dp[i][j-1]+(Y[j]-Y[j-1]-1)*val[i][j-1]); } ll ans=0; for(int i=1;i<=totA;i++) for(int j=1;j<=totB;j++) if(X[i]+Y[j]<=m) ans=max(ans,(m-X[i]-Y[j])*val[i][j]+dp[i][j]); printf("%lld\n",ans); return 0; }
- 定義dp[i][j] 為屬性ai到達