BZOJ 1560 火星藏宝图(DP)
思路:发现如果从A能到B,B能到C,那么一定A能到C,且根据不等式:A^2+B^2<=(A+B)^2,而且权值没有负数,因此经过B比不经过B要优,因此,我们从左上到右下做,每一列,我们只记录之前做过的最下面的那个位置的信息,然后从这个位置的前几列里面寻找最优。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define ll long long 7 #define inf 999999999 8 struct Point{ 9 int x,y,w; 10 Point(){} 11 Point(int x0,int y0):x(x0),y(y0){} 12 }a[200005]; 13 int n,m,b[200005],c[200005]; 14 int read(){ 15 int t=0,f=1;char ch=getchar(); 16 while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} 17 while (ch<='9'&&ch>='0'){t=t*10+ch-'0';ch=getchar();} 18 return t*f; 19 } 20 bool cmp(Point p1,Point p2){ 21 if (p1.x!=p2.x) return p1.x<p2.x; 22 return p1.y<p2.y; 23 } 24 int sqr(int x){ 25 return x*x; 26 } 27 int dis(Point p1,Point p2){ 28 return sqr(p1.x-p2.x)+sqr(p1.y-p2.y); 29 } 30 int main(){ 31 n=read();m=read(); 32 for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].w=read(); 33 std::sort(a+1,a+1+n,cmp); 34 for (int i=1;i<=m;i++) b[i]=-inf; 35 b[1]=a[1].w; 36 c[1]=1; 37 int tmp; 38 for (int i=2;i<=n;i++){ 39 int x=a[i].x,y=a[i].y,w=a[i].w; 40 tmp=-inf; 41 for (int j=1;j<=y;j++) 42 tmp=std::max(tmp,b[j]-dis(Point(x,y),Point(c[j],j))); 43 tmp+=w; 44 b[y]=tmp;c[y]=x; 45 } 46 printf("%d\n",tmp); 47 }