首先这种题目肯定是要先排序,以x为第一关键字,y为第二关键字
不难想到O(n2)的dp,下面显然要优化
不难发现,由于两点的耗费是坐标差的平方的和,不带根号,
因此,不难发现一个很有用的性质,如果从A点能到C点,C点到B,这样走C点一定比不走C点优
于是不难想到我们要维护y坐标上的上x最大的点,这个点一定是当前相同y坐标中收益最大的
设f[i]为到点i的最大收益,d[y]为当前纵坐标y上最大收益,则f[i]=max(d[k]-dis+v) 1<=k<=y[i]
但这样还是超时了,我们要在进一步优化
由于m<=1000,而n比较大,所以会有许多点有相同的x坐标
对于拥有相同x坐标的点,除了y最小的点我们需要从1开始转移
很容易想到,其他点完全只需要从y[i-1]~y[i]内转移
于是这样就过了

 1 var w:array[0..1010,0..1010] of longint;
 2     a,b,v,r:array[0..200010] of longint;
 3     f:array[0..1010] of longint;
 4     ans,j,n,m,i,x,y,z,t:longint;
 5 
 6 function max(a,b:longint):longint;
 7   begin
 8     if a>b then exit(a) else exit(b);
 9   end;
10 
11 function dis(x,y,a,b:longint):longint;
12   begin
13     exit(sqr(x-a)+sqr(y-b));
14   end;
15 
16 begin
17   readln(n,m);
18   for i:=1 to n do
19   begin
20     readln(x,y,z);
21     w[x,y]:=z;
22   end;
23   for i:=1 to m do
24     for j:=1 to m do
25       if w[i,j]<>0 then
26       begin
27         inc(t);
28         a[t]:=i;
29         b[t]:=j;
30         v[t]:=w[i,j];
31       end;
32 
33   f[1]:=v[1];
34   r[1]:=1;
35   for i:=2 to n do
36   begin
37     ans:=-2000000;
38     if a[i]=a[i-1] then
39     begin
40       for j:=b[i-1] to b[i] do
41         if r[j]<>0 then ans:=max(ans,f[j]-dis(a[i],b[i],r[j],j));
42     end
43     else begin
44       for j:=1 to b[i] do
45         if r[j]<>0 then ans:=max(ans,f[j]-dis(a[i],b[i],r[j],j));
46     end;
47     ans:=ans+v[i];
48     f[b[i]]:=ans;
49     r[b[i]]:=a[i];
50   end;
51   writeln(ans);
52 end.
53 
54  
View Code

 

posted on 2014-10-14 22:36  acphile  阅读(231)  评论(0编辑  收藏  举报