1. 程式人生 > >bzoj2037 [Sdoi2008]Sue的小球

bzoj2037 [Sdoi2008]Sue的小球

getchar 保留 成了 sandy size scrip lin pen 得到

Description

Sue和Sandy最近迷上了一個電腦遊戲,這個遊戲的故事發在美麗神秘並且充滿刺激的大海上,Sue有一支輕便小巧的小船。然而,Sue的目標並不是當一個海盜,而是要收集空中漂浮的彩蛋,Sue有一個秘密武器,只要她將小船劃到一個彩蛋的正下方,然後使用秘密武器便可以在瞬間收集到這個彩蛋。然而,彩蛋有一個魅力值,這個魅力值會隨著彩蛋在空中降落的時間而降低,Sue要想得到更多的分數,必須盡量在魅力值高的時候收集這個彩蛋,而如果一個彩蛋掉入海中,它的魅力值將會變成一個負數,但這並不影響Sue的興趣,因為每一個彩蛋都是不同的,Sue希望收集到所有的彩蛋。 然而Sandy就沒有Sue那麽浪漫了,Sandy希望得到盡可能多的分數,為了解決這個問題,他先將這個遊戲抽象成了如下模型: 以Sue的初始位置所在水平面作為x軸。 一開始空中有N個彩蛋,對於第i個彩蛋,他的初始位置用整數坐標(xi, yi)表示,遊戲開始後,它勻速沿y軸負方向下落,速度為vi單位距離/單位時間。Sue的初始位置為(x0, 0),Sue可以沿x軸的正方向或負方向移動,Sue的移動速度是1單位距離/單位時間,使用秘密武器得到一個彩蛋是瞬間的,得分為當前彩蛋的y坐標的千分之一。 現在,Sue和Sandy請你來幫忙,為了滿足Sue和Sandy各自的目標,你決定在收集到所有彩蛋的基礎上,得到的分數最高。

Input

第一行為兩個整數N, x0用一個空格分隔,表示彩蛋個數與Sue的初始位置。 第二行為N個整數xi,每兩個數用一個空格分隔,第i個數表示第i個彩蛋的初始橫坐標。 第三行為N個整數yi,每兩個數用一個空格分隔,第i個數表示第i個彩蛋的初始縱坐標。 第四行為N個整數vi,每兩個數用一個空格分隔,第i個數表示第i個彩蛋勻速沿y軸負方向下落的的速度。

Output

一個實數,保留三位小數,為收集所有彩蛋的基礎上,可以得到最高的分數。

Sample Input

3 0
-4 -2 2
22 30 26
1 9 8

Sample Output

0.000

數據範圍:
N < = 1000,對於100%的數據。 -10^4 < = xi,yi,vi < = 10^4

正解:區間$dp$。

首先我們肯定是會先取完$x$軸上連續的一段再取這一段外面的。

所以我們把球按照$x$軸排序以後就是一個很簡單的區間$dp$。

設$f[l][r][0/1]$表示取完$[l,r]$的球,最後是在左邊/右邊取的得分最大值。

直接討論轉移即可,註意計算貢獻時要把還沒取到的球已經產生的費用算上。

復雜度$O(n^{2})$。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define N (1005)
 6
7 using namespace std; 8 9 struct data{ int x,y,z; }p[N]; 10 11 int sum[N],n,x0; 12 ll f[N][N][2]; 13 14 il int gi(){ 15 RG int x=0,q=1; RG char ch=getchar(); 16 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 17 if (ch==-) q=-1,ch=getchar(); 18 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 19 return q*x; 20 } 21 22 il int cmp(const data &a,const data &b){ return a.x<b.x; } 23 24 int main(){ 25 #ifndef ONLINE_JUDGE 26 freopen("sue.in","r",stdin); 27 freopen("sue.out","w",stdout); 28 #endif 29 n=gi(),x0=gi(); 30 for (RG int i=1;i<=n;++i) p[i].x=gi(); 31 for (RG int i=1;i<=n;++i) p[i].y=gi(); 32 for (RG int i=1;i<=n;++i) p[i].z=gi(); 33 sort(p+1,p+n+1,cmp),memset(f,-0x3f3f3f,sizeof(f)); 34 for (RG int i=1;i<=n;++i) sum[i]=sum[i-1]+p[i].z; 35 for (RG int i=1;i<=n;++i) 36 f[i][i][0]=f[i][i][1]=1LL*p[i].y-1LL*fabs(x0-p[i].x)*sum[n]; 37 for (RG int len=1;len<n;++len) 38 for (RG int l=1,r;l+len<=n;++l){ 39 r=l+len; 40 f[l][r][0]=max(f[l][r][0],f[l+1][r][0]-1LL*(p[l+1].x-p[l].x)*(sum[n]-sum[r]+sum[l])+p[l].y); 41 f[l][r][0]=max(f[l][r][0],f[l+1][r][1]-1LL*(p[r].x-p[l].x)*(sum[n]-sum[r]+sum[l])+p[l].y); 42 f[l][r][1]=max(f[l][r][1],f[l][r-1][0]-1LL*(p[r].x-p[l].x)*(sum[n]-sum[r-1]+sum[l-1])+p[r].y); 43 f[l][r][1]=max(f[l][r][1],f[l][r-1][1]-1LL*(p[r].x-p[r-1].x)*(sum[n]-sum[r-1]+sum[l-1])+p[r].y); 44 } 45 printf("%0.3lf\n",0.001*max(f[1][n][0],f[1][n][1])); return 0; 46 }

bzoj2037 [Sdoi2008]Sue的小球