1. 程式人生 > >【BZOJ1560】【JSOI2009】火星藏寶圖 [DP]

【BZOJ1560】【JSOI2009】火星藏寶圖 [DP]

.com bsp std spa sin names set mat space

火星藏寶圖

Time Limit: 10 Sec Memory Limit: 64 MB
[Submit][Status][Discuss]

Description

  技術分享

Input

  技術分享

Output

  技術分享

Sample Input

  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 #include<iostream>    
 2 #include<string>    
 3 #include<algorithm>    
 4 #include<cstdio>    
 5 #include<cstring>    
 6
#include<cstdlib> 7 #include<cmath> 8 using namespace std; 9 typedef long long s64; 10 11 const int ONE = 500005; 12 const int INF = 2147483640; 13 14 int n,m; 15 int pos[ONE]; 16 int f[ONE]; 17 18 struct power 19 { 20 int x,y,z; 21 }a[ONE]; 22 23 bool cmp(const
power &a, const power &b) 24 { 25 if(a.x != b.x) return a.x < b.x; 26 return a.y < b.y; 27 } 28 29 int cost(int Ax, int Ay, int Bx, int By) 30 { 31 return (Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By); 32 } 33 34 int get() 35 { 36 int res=1,Q=1;char c; 37 while( (c=getchar())<48 || c>57 ) 38 if(c==-)Q=-1; 39 res=c-48; 40 while( (c=getchar())>=48 && c<=57 ) 41 res=res*10+c-48; 42 return res*Q; 43 } 44 45 int main() 46 { 47 n = get(); m = get(); 48 for(int i=1; i<=n; i++) 49 a[i].x = get(), a[i].y = get(), a[i].z = get(); 50 sort(a+1, a+n+1, cmp); 51 52 memset(f, -127, sizeof(f)); 53 pos[1] = 1; f[1] = 0; 54 for(int id=1; id<=n; id++) 55 { 56 int x = a[id].x, y = a[id].y; 57 int record = -INF; 58 for(int j=1; j<=y; j++) 59 if(pos[j]) 60 record = max( record, f[j] - cost(pos[j],j, x,y) ); 61 62 pos[y] = x; 63 f[y] = record + a[id].z; 64 } 65 66 printf("%d", f[m]); 67 } 68
View Code

【BZOJ1560】【JSOI2009】火星藏寶圖 [DP]