BZOJ2037: [Sdoi2008]Sue的小球

n<=1000个球在坐标系中从天上掉下,给每个球初始位置(Xi,Yi)和下落速度Vi,我从x0开始在x轴上走,走一个单位一秒,走到一处可以0秒射击一个横坐标相同的球,得分为球的当前纵坐标,求打完所有求最大得分/1000。

这是一种当前决策影响后续代价的DP,需要在某一步决策的同时把该决策对后面的影响同时计算。显然不会走过一个点不打,所以打的球是x坐标连续的区间。f(i,j,0/1)--区间i到j所有球打完,最后落在左/右端点。你可以用它表示总代价,但我喜欢把它作为:打完这个区间后,算上后面的影响的,最多剩多少价值,所以需要初始化为总价值也就是y坐标的和,然后dp过程中算上一起的代价。

记得初始化。S(i,j)表示:除了(i,j)这个区间外其他点的v的和,这可以记个前缀和解决。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<math.h>
 6 //#include<queue>
 7 //#include<iostream>
 8 using namespace std;
 9 
10 int n,x0;
11 #define maxn 1011
12 struct Point
13 {
14     int x,y,v;
15     bool operator < (const Point &b) const {return x<b.x;}
16 }a[maxn];
17 int f[maxn][maxn][2],sum[maxn];
18 int main()
19 {
20     scanf("%d%d",&n,&x0);
21     int toty=0;
22     for (int i=1;i<=n;i++) scanf("%d",&a[i].x);
23     for (int i=1;i<=n;i++) scanf("%d",&a[i].y),toty+=a[i].y;
24     for (int i=1;i<=n;i++) scanf("%d",&a[i].v);
25     sort(a+1,a+1+n);
26     sum[0]=0;for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i].v;
27     for (int i=1;i<=n;i++)
28         for (int j=i;j<=n;j++)
29             f[i][j][0]=f[i][j][1]=toty;
30     for (int i=1;i<=n;i++) f[i][i][0]=f[i][i][1]=toty-fabs(x0-a[i].x)*sum[n];
31     for (int len=1;len<n;len++)
32         for (int i=1;i<=n-len;i++)
33         {
34             int j=i+len;
35             f[i][j][0]=max(f[i+1][j][0]-(sum[n]-sum[j]+sum[i])*(a[i+1].x-a[i].x),
36             f[i+1][j][1]-(sum[n]-sum[j]+sum[i])*(a[j].x-a[i].x));
37             f[i][j][1]=max(f[i][j-1][0]-(sum[n]-sum[j-1]+sum[i-1])*(a[j].x-a[i].x),
38             f[i][j-1][1]-(sum[n]-sum[j-1]+sum[i-1])*(a[j].x-a[j-1].x));
39         }
40     printf("%.3f\n",max(f[1][n][0],f[1][n][1])*1.0/1000.0);
41     return 0;
42 }
View Code

 

posted @ 2017-09-27 16:23  Blue233333  阅读(207)  评论(0编辑  收藏  举报