1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 struct data 6 { 7 int x,y,v; 8 }a[1009]; 9 int f[1009][1009][2],n,x0,b[1009],sum[1009],tot; 10 bool cmp(data a1,data a2) 11 { 12 return a1.x<a2.x; 13 } 14 int main() 15 { 16 scanf("%d%d",&n,&x0); 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%d",&a[i].x); 20 a[i].x-=x0; 21 } 22 for(int i=1;i<=n;i++) 23 { 24 scanf("%d",&a[i].y); 25 tot+=a[i].y; 26 } 27 for(int i=1;i<=n;i++) 28 scanf("%d",&a[i].v); 29 sort(a,a+n+1,cmp); 30 for(int i=0;i<=n;i++) 31 b[i]=a[i].x; 32 x0=lower_bound(b,b+n+1,0)-b; 33 for(int i=x0-1;i>=0;i--) 34 sum[i]=sum[i+1]+a[i].v; 35 for(int i=x0+1;i<=n;i++) 36 sum[i]=sum[i-1]+a[i].v; 37 for(int i=x0+1;i<=n;i++) 38 { 39 f[x0][i][1]=f[x0][i-1][1]+(sum[n]+sum[0]-sum[i-1])*abs(a[i].x-a[i-1].x); 40 f[x0][i][0]=f[x0][i][1]+(sum[n]+sum[0]-sum[i])*abs(a[i].x); 41 } 42 for(int i=x0-1;i>=0;i--) 43 { 44 f[i][x0][0]=f[i+1][x0][0]+(sum[n]+sum[0]-sum[i+1])*abs(a[i].x-a[i+1].x); 45 f[i][x0][1]=f[i][x0][0]+(sum[n]+sum[0]-sum[i])*abs(a[i].x); 46 } 47 for(int i=x0-1;i>=0;i--) 48 for(int j=x0+1;j<=n;j++) 49 { 50 f[i][j][0]=f[i+1][j][0]+(sum[0]-sum[i+1]+sum[n]-sum[j])*abs(a[i].x-a[i+1].x); 51 f[i][j][0]=min(f[i][j][0],f[i+1][j][1]+(sum[0]-sum[i+1]+sum[n]-sum[j])*abs(a[i].x-a[j].x)); 52 f[i][j][1]=f[i][j-1][1]+(sum[0]-sum[i]+sum[n]-sum[j-1])*abs(a[j].x-a[j-1].x); 53 f[i][j][1]=min(f[i][j][1],f[i][j-1][0]+(sum[0]-sum[i]+sum[n]-sum[j-1])*abs(a[j].x-a[i].x)); 54 } 55 int x0=min(f[0][n][1],f[0][n][0]); 56 printf("%.3lf\n",(tot-x0)*0.001); 57 return 0; 58 }
很像以前在codevs上做的关路灯那个题,区间型DP,可知他不可能越过一盏灯去关另一盏。所以从起点开始,依次向两边扩展,f[i][j][0]表示关完区间[i,j]停在左边,[1]表示停在右边。
f[i][j][0]即可从f[i+1][j][0]转移来,又可从f[i+1][j][1]转移来。