【BZOJ1560】【JSOI2009】火星藏宝图 [DP]

火星藏宝图

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

 

posted @ 2017-05-28 11:05  BearChild  阅读(200)  评论(0编辑  收藏  举报