首先这种题目肯定是要先排序,以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