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]转移来。

posted on 2016-03-18 22:40  xiyuedong  阅读(156)  评论(0编辑  收藏  举报