链接:http://acm.hdu.edu.cn/showproblem.php?pid=6447
思路:很容易推得dp转移公式:dp[i][j] = max(dp[i][j-1],dp[i-1][j],dp[i-1][j-1]+val[i][j]) ,但是很明显离散化后也无法储存这些点,我们可以用树状数组对这个状态转移公式进行优化,我们先以y轴为第一优先级从小到大排序,以x轴为第二优先级从大到小排序,对x轴坐标进行离散化,这样我们就只需要维护x轴上的最大值即可,状态转移方程可优化为: dp[i] = max(dp[i],dp[k]+val) 其中 0<k<i,dp[k]表示dp[1]到dp[i-1]的最大值(可用树状数组维护)
实现代码:
#include<bits/stdc++.h> using namespace std; const int M = 1e5+10; struct node{ int x,y,val; bool operator < (const node &k)const{ if(y == k.y) return x > k.x; return y < k.y; } }a[M]; int c[M],pos[M],n; void add(int x,int val){ while(x <= n){ c[x] = max(c[x],val); x += (x&-x); } } int getsum(int x){ int res = 0; while(x){ res = max(res,c[x]); x -= (x&-x); } return res; } int main(){ int t; scanf("%d",&t); while(t--){ memset(c,0,sizeof(c)); scanf("%d",&n); for(int i = 1;i <= n;i ++){ scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val); pos[i] = a[i].x; } sort(a+1,a+1+n); sort(pos+1,pos+1+n); int ans = 0; for(int i = 1;i <= n;i ++){ int cnt = lower_bound(pos+1,pos+1+n,a[i].x)-pos; int num = a[i].val + getsum(cnt-1); ans = max(ans,num); add(cnt,num); } printf("%d ",ans); } }