火星藏宝图
Time Limit: 10 Sec Memory Limit: 64 MB
Description
Output
4 10
1 1 20
10 10 10
3 5 60
5 3 30
Sample Output
-4
HINT
1<= M <=2000, 2<= N <=100000.
Main idea
每个点上有一个收益,从一个点走到另外一个点的花费是欧几里得距离的平方,问从(1,1)走到(m,m)的最大收益。
Solution
首先,运用DP。而且若A < C < B,显然则有 (A-B)^2 > (A-C)^2 + (C-B)^2。
那么我们对横坐标排序一下,可以保证横向的大小关系。然后对于一个转移,每一纵向只有最接近它的点有用。这样就可以做到**O(nm)**了。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include<bits/stdc++.h> using namespace std; typedef long long s64;
const int ONE = 500005; const int INF = 2147483640;
int n,m; int pos[ONE]; int f[ONE];
struct power { int x,y,z; }a[ONE];
bool cmp(const power &a, const power &b) { if(a.x != b.x) return a.x < b.x; return a.y < b.y; }
int cost(int Ax, int Ay, int Bx, int By) { return (Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By); }
int get() { int res=1,Q=1;char c; while( (c=getchar())<48 || c>57 ) if(c=='-')Q=-1; res=c-48; while( (c=getchar())>=48 && c<=57 ) res=res*10+c-48; return res*Q; }
int main() { n = get(); m = get(); for(int i=1; i<=n; i++) a[i].x = get(), a[i].y = get(), a[i].z = get(); sort(a+1, a+n+1, cmp);
memset(f, -127, sizeof(f)); pos[1] = 1; f[1] = 0; for(int id=1; id<=n; id++) { int x = a[id].x, y = a[id].y; int record = -INF; for(int j=1; j<=y; j++) if(pos[j]) record = max( record, f[j] - cost(pos[j],j, x,y) );
pos[y] = x; f[y] = record + a[id].z; }
printf("%d", f[m]); }
|