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 }