【DP SDOI2008 BZOJ 2037】Sue的小球
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 222 30 261 9 8Sample Output
0.000Data
N < = 1000,對于100%的數據。
?104<=xi,yi,vi<=104
I think
???? 參見2009年國家集訓隊論文
徐源盛《對一類動態規劃問題的研究》
???? 首先對每一顆彩蛋按照橫坐標x排序,用f1[i][j] 記已收集第i~j顆彩蛋停在i處時的最高分數,f2[i][j] 記已收集第i~j顆彩蛋最后停在j處時的最高分數,w[i][j] 記除i~j顆彩蛋之外所有彩蛋速度之和(用前綴和實現)。
???? 已收集第i~j顆彩蛋后,由第i顆彩蛋移向第i-1顆彩蛋的過程中,只有第1~i-1顆,j+1~n顆彩蛋在下落,因此可以得到遞推式:
f2[i][j]=max(f1[i][j?1]?w[i][j?1]?(x[j]?x[i]),f2[i][j?1]?w[i][j?1]?(x[j]?x[j?1]));
???? 最終結果 ANS=max(f1[1][n],f2[1][n]);
???? 由中間向兩邊遞推,我的代碼是由兩邊到中間記憶化搜索。
Code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std;const int sm = 1e3+5;struct ball{int x,y,v; }b[sm];int xx,N,inf; int V[sm],f[2][sm][sm]; double ans;bool cmp(ball a,ball b) {return a.x<b.x; }int dfs(int t,int i,int j) {if(i>j||f[t][i][j]!=inf)return f[t][i][j];if(i==j) return f[0][i][j]=f[1][i][j]=-abs(xx-b[i].x)*V[N]+b[i].y;int tmp=inf,w;if(t==0) {w=V[N]-(V[j]-V[i]);tmp=max(tmp,dfs(0,i+1,j)-w*abs(b[i+1].x-b[i].x));tmp=max(tmp,dfs(1,i+1,j)-w*abs(b[j].x-b[i].x));return f[t][i][j]=tmp+b[i].y;}else {w=V[N]-(V[j-1]-V[i-1]);tmp=max(tmp,dfs(0,i,j-1)-w*abs(b[i].x-b[j].x));tmp=max(tmp,dfs(1,i,j-1)-w*abs(b[j-1].x-b[j].x));return f[t][i][j]=tmp+b[j].y;} }int main() { scanf("%d%d",&N,&xx);for(int i=1;i<=N;++i)scanf("%d",&b[i].x);for(int i=1;i<=N;++i)scanf("%d",&b[i].y);for(int i=1;i<=N;++i)scanf("%d",&b[i].v);sort(b+1,b+N+1,cmp);for(int i=1;i<=N;++i)V[i]=V[i-1]+b[i].v;memset(f,-0x3f,sizeof(f));inf=f[0][0][0];ans=1.0*max(dfs(0,1,N),dfs(1,1,N));printf("%.3lf\n",ans/1000);return 0; }總結
以上是生活随笔為你收集整理的【DP SDOI2008 BZOJ 2037】Sue的小球的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mysql 1044错误代码:Acces
- 下一篇: 数据竞赛专题 | 从赛题理解到竞赛入门基