HDU6447 YJJ's Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP
Posted mizersy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU6447 YJJ's Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP相关的知识,希望对你有一定的参考价值。
YJJ‘s Salesman
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 253 Accepted Submission(s): 62
Problem Description
YJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the way to destination.
One day, he is going to travel from city A to southeastern city B. Let us assume that A is (0,0) on the rectangle map and B (109,109). YJJ is so busy so he never turn back or go twice the same way, he will only move to east, south or southeast, which means, if YJJ is at (x,y) now (0≤x≤109,0≤y≤109), he will only forward to (x+1,y), (x,y+1) or (x+1,y+1).
On the rectangle map from (0,0) to (109,109), there are several villages scattering on the map. Villagers will do business deals with salesmen from northwestern, but not northern or western. In mathematical language, this means when there is a village k on (xk,yk) (1≤xk≤109,1≤yk≤109), only the one who was from (xk?1,yk?1) to (xk,yk) will be able to earn vk dollars.(YJJ may get different number of dollars from different village.)
YJJ has no time to plan the path, can you help him to find maximum of dollars YJJ can get.
One day, he is going to travel from city A to southeastern city B. Let us assume that A is (0,0) on the rectangle map and B (109,109). YJJ is so busy so he never turn back or go twice the same way, he will only move to east, south or southeast, which means, if YJJ is at (x,y) now (0≤x≤109,0≤y≤109), he will only forward to (x+1,y), (x,y+1) or (x+1,y+1).
On the rectangle map from (0,0) to (109,109), there are several villages scattering on the map. Villagers will do business deals with salesmen from northwestern, but not northern or western. In mathematical language, this means when there is a village k on (xk,yk) (1≤xk≤109,1≤yk≤109), only the one who was from (xk?1,yk?1) to (xk,yk) will be able to earn vk dollars.(YJJ may get different number of dollars from different village.)
YJJ has no time to plan the path, can you help him to find maximum of dollars YJJ can get.
Input
The first line of the input contains an integer T (1≤T≤10),which is the number of test cases.
In each case, the first line of the input contains an integer N (1≤N≤105).The following N lines, the k-th line contains 3 integers, xk,yk,vk (0≤vk≤103), which indicate that there is a village on (xk,yk) and he can get vk dollars in that village.
The positions of each village is distinct.
In each case, the first line of the input contains an integer N (1≤N≤105).The following N lines, the k-th line contains 3 integers, xk,yk,vk (0≤vk≤103), which indicate that there is a village on (xk,yk) and he can get vk dollars in that village.
The positions of each village is distinct.
Output
The maximum of dollars YJJ can get.
Sample Input
1
3
1 1 1
1 2 2
3 3 1
Sample Output
3
Source
第一反应是最短路,但是没法建图而且会TLE。场上一直在想怎么DP,无奈实在点数太多不会处理,也没做过这种二维最长上升序列。
队友临结束还有三分钟离散化+线段树AC....菜鸡默默补题
题解:
DP思路很容易想到:dp[i][j] = max{dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+v[i][j]},但是O(n^2)的dp肯定会T,显然最大值肯定会在村庄处取得,所以可以离散化减少点数,其次因为人只能向右或向下或向右下移动,所以可以从左往右,从上到下更新,若用f[j]表示走到第j列所能取得的最大值,则走到第i行第j列的f[j] = max{f[j],max(f[j-1])+v[i][j]},本题先离散化用线段树维护前k列的最值,然后按行从小到大dp即可。
1 #include <bits/stdc++.h> 2 #define mid ((tr[d].l + tr[d].r)>>1) 3 #define lc (d << 1) 4 #define rc (d << 1|1) 5 using namespace std; 6 const int maxn = 1e5+5; 7 struct Tr{ 8 int l,r,mx; 9 }tr[maxn*4]; 10 struct Node{ 11 int x,y,w; 12 bool operator < (const Node &a)const{ 13 //????? 14 return (x == a.x) ? y > a.y : x < a.x; 15 } 16 }node[maxn]; 17 int T,n; 18 int hash_x[maxn],hash_y[maxn]; 19 int n1,n2; 20 21 void build(int d,int l,int r){ 22 tr[d].l = l,tr[d].r = r,tr[d].mx = 0; 23 if (tr[d].l == tr[d].r){ 24 return; 25 } 26 build(lc,l,mid); build(rc,mid+1,r); 27 } 28 29 int query(int d,int l,int r){ 30 if (tr[d].l == l && tr[d].r == r){ 31 return tr[d].mx; 32 } 33 if (mid >= r) return query(lc,l,r); 34 else if (mid < l) return (rc,l,r); 35 else return max(query(lc,l,mid),query(rc,mid+1,r)); 36 } 37 38 void update(int d,int pos,int w){ 39 if (tr[d].l == tr[d].r && tr[d].r == pos) { 40 tr[d].mx = max(w,tr[d].mx); 41 return; 42 } 43 if (mid >= pos) update(lc,pos,w); 44 else update(rc,pos,w); 45 tr[d].mx = max(tr[lc].mx,tr[rc].mx); 46 } 47 48 int main(){ 49 scanf("%d",&T); 50 while(T--){ 51 scanf("%d",&n); 52 for (int i = 0;i < n;++i){ 53 scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].w); 54 hash_x[i] = node[i].x,hash_y[i] = node[i].y; 55 } 56 sort(hash_x,hash_x+n); 57 sort(hash_y,hash_y+n); 58 n1 = unique(hash_x,hash_x+n) - hash_x; 59 n2 = unique(hash_y,hash_y+n) - hash_y; 60 for (int i = 0;i < n;++i){ 61 node[i].x = lower_bound(hash_x,hash_x+n1,node[i].x) - hash_x; 62 node[i].y = lower_bound(hash_y,hash_y+n2,node[i].y) - hash_y; 63 } 64 sort(node,node+n); 65 build(1,0,n); 66 int ans = 0; 67 for (int i = 0;i < n;++i){ 68 int tmp; 69 if (node[i].y == 0) tmp = node[i].w; 70 else tmp = query(1,0,node[i].y-1) + node[i].w; 71 update(1,node[i].y,tmp); 72 ans = max(ans,tmp); 73 } 74 printf("%d ",ans); 75 } 76 return 0; 77 }
以上是关于HDU6447 YJJ's Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP的主要内容,如果未能解决你的问题,请参考以下文章
[HDU 6447][YJJ's Salesman][2018CCPC网络选拔赛 1010][离散化+线段树+DP]
HDU6447 YJJ's Salesman 2018中国大学生程序设计竞赛 - 网络选拔赛1010 离散化+线段树+DP
HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp