【SDOI2008】Sue的小球
Description
Sue和Sandy最近迷上了一個(gè)電腦游戲,這個(gè)游戲的故事發(fā)在美麗神秘并且充滿刺激的大海上,Sue有一支輕便小巧的小船。然而,Sue的目標(biāo)并不是當(dāng)一個(gè)海盜,而是要收集空中漂浮的彩蛋,Sue有一個(gè)秘密武器,只要她將小船劃到一個(gè)彩蛋的正下方,然后使用秘密武器便可以在瞬間收集到這個(gè)彩蛋。然而,彩蛋有一個(gè)魅力值,這個(gè)魅力值會(huì)隨著彩蛋在空中降落的時(shí)間而降低,Sue要想得到更多的分?jǐn)?shù),必須盡量在魅力值高的時(shí)候收集這個(gè)彩蛋,而如果一個(gè)彩蛋掉入海中,它的魅力值將會(huì)變成一個(gè)負(fù)數(shù),但這并不影響Sue的興趣,因?yàn)槊恳粋€(gè)彩蛋都是不同的,Sue希望收集到所有的彩蛋。?
然而Sandy就沒有Sue那么浪漫了,Sandy希望得到盡可能多的分?jǐn)?shù),為了解決這個(gè)問(wèn)題,他先將這個(gè)游戲抽象成了如下模型:?
以Sue的初始位置所在水平面作為x軸。?
一開始空中有N個(gè)彩蛋,對(duì)于第i個(gè)彩蛋,他的初始位置用整數(shù)坐標(biāo)(xi, yi)表示,游戲開始后,它勻速沿y軸負(fù)方向下落,速度為vi單位距離/單位時(shí)間。Sue的初始位置為(x0, 0),Sue可以沿x軸的正方向或負(fù)方向移動(dòng),Sue的移動(dòng)速度是1單位距離/單位時(shí)間,使用秘密武器得到一個(gè)彩蛋是瞬間的,得分為當(dāng)前彩蛋的y坐標(biāo)的千分之一。?
現(xiàn)在,Sue和Sandy請(qǐng)你來(lái)幫忙,為了滿足Sue和Sandy各自的目標(biāo),你決定在收集到所有彩蛋的基礎(chǔ)上,得到的分?jǐn)?shù)最高。
Input
第一行為兩個(gè)整數(shù)N, x0用一個(gè)空格分隔,表示彩蛋個(gè)數(shù)與Sue的初始位置。?
第二行為N個(gè)整數(shù)xi,每?jī)蓚€(gè)數(shù)用一個(gè)空格分隔,第i個(gè)數(shù)表示第i個(gè)彩蛋的初始橫坐標(biāo)。?
第三行為N個(gè)整數(shù)yi,每?jī)蓚€(gè)數(shù)用一個(gè)空格分隔,第i個(gè)數(shù)表示第i個(gè)彩蛋的初始縱坐標(biāo)。?
第四行為N個(gè)整數(shù)vi,每?jī)蓚€(gè)數(shù)用一個(gè)空格分隔,第i個(gè)數(shù)表示第i個(gè)彩蛋勻速沿y軸負(fù)方向下落的的速度。
Output
一個(gè)實(shí)數(shù),保留三位小數(shù),為收集所有彩蛋的基礎(chǔ)上,可以得到最高的分?jǐn)?shù)。
Sample Input
3 0 -4 -2 2 22 30 26 1 9 8
Sample Output
0.000
Hint
N<=20,對(duì)于30%的數(shù)據(jù)。?
N<=100,對(duì)于100%的數(shù)據(jù)。?
-10^4 <= xi,yi,vi <= 10^4,對(duì)于100%的數(shù)據(jù)。?
【分析】
顯然,Sue沒浪費(fèi)一單位時(shí)間,所有他沒有接到的彩蛋都會(huì)損失一定的分?jǐn)?shù)。
設(shè)
a[n]表示Sue起始點(diǎn)左邊的所有點(diǎn)距Sue的距離,按從小到大排序;
b[m]表示Sue起始點(diǎn)右邊的所有點(diǎn)距Sue的距離,按從小到大排序。
Sum_a[i]表示一單位時(shí)間a數(shù)組中前i個(gè)彩蛋損失的分?jǐn)?shù)的前綴和;
Sum_b[i]表示一單位時(shí)間b數(shù)組中前i個(gè)彩蛋損失的分?jǐn)?shù)的前綴和。
用動(dòng)態(tài)規(guī)劃解決此題:
設(shè)狀態(tài)為f[i][j][k]表示Sue的起始點(diǎn)左邊收集了i個(gè)彩蛋,右邊收集了j個(gè)彩蛋,并且最終停留在位置k(k=0表示停在左邊i位置上,k=1表示停在右邊j位置上)時(shí)最小的損失。
狀態(tài)轉(zhuǎn)移方程為:
f[i][j][0] = min{
? ? ? ? ? ? ? ?f[i-1][j][0] + (a[i]-a[i-1])*(Sum_a[n]-Sum_a[i-1]+Sum_b[m]-Sum_b[j]),
f[i-1][j][1] + (a[i]+b[j])*(Sum_a[n]-Sum[i-1]+Sum_b[m]-Sum_b[j]
? ? ? ? ? ? ? ? }
f[i][j][1] = min{
? ? ? ? ? ? ? ?f[i][j-1][1] + (b[j]-b[j-1])*(Sum_a[n]-Sum_a[i]+Sum_b[m]-Sum_b[j-1],
? ? ? f[i][j-1][0] + (a[i]+b[j])*(Sum_a[n]-Sum_a[i]+Sum_b[m]-Sum_b[j-1])
? ? ? ? ? ? ? ? }
最后的結(jié)果即為初始分?jǐn)?shù)減去min{f[n][m][0], f[n][m][1]}
【代碼】
/*ID:CiocioLANG:C++DATE:2013-11-30TASK:SDOI 2008 Sue */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <queue>using namespace std;#define MAXN 1005 #define INF 999999999struct node{int x,sum;friend bool operator<(const node &A,const node &B){return A.x<B.x;} }; node A[MAXN],B[MAXN]; int N,x0,f[MAXN][MAXN][2],x[MAXN],y[MAXN],v[MAXN]; int n,m,tot;void _init() {scanf("%d%d",&N,&x0);for(int i=1;i<=N;i++) scanf("%d",&x[i]);for(int i=1;i<=N;i++) scanf("%d",&y[i]),tot+=y[i];for(int i=1;i<=N;i++) scanf("%d",&v[i]);for(int i=1;i<=N;i++){if(x[i]<x0) //前面的放入結(jié)構(gòu)體A{n++;A[n].x=x0-x[i];A[n].sum=v[i];} else if(x[i]>x0) //后面的放入B{m++;B[m].x=x[i]-x0;B[m].sum=v[i];}}sort(A+1,A+n+1);sort(B+1,B+m+1); //排序for(int i=1;i<=n;i++) //求出代價(jià)的前綴和A[i].sum+=A[i-1].sum;for(int i=1;i<=m;i++) B[i].sum+=B[i-1].sum; }void _solve() {for(int i=1;i<=n;i++) //邊界{f[i][0][0]=f[i-1][0][0]+(A[i].x-A[i-1].x)*(B[m].sum+A[n].sum-A[i-1].sum);f[i][0][1]=f[i][0][0]+A[i].x*(B[m].sum+A[n].sum-A[i].sum);}for(int i=1;i<=m;i++){f[0][i][1]=f[0][i-1][1]+(B[i].x-B[i-1].x)*(A[n].sum+B[m].sum-B[i-1].sum);f[0][i][0]=f[0][i][1]+B[i].x*(A[n].sum+B[m].sum-B[i].sum);}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) //DP{int delta1=A[n].sum-A[i-1].sum+B[m].sum-B[j].sum;int delta2=A[n].sum-A[i].sum+B[m].sum-B[j-1].sum;f[i][j][0]=min(f[i-1][j][0]+(A[i].x-A[i-1].x)*delta1,f[i-1][j][1]+(A[i].x+B[j].x)*delta1);f[i][j][1]=min(f[i][j-1][0]+(A[i].x+B[j].x)*delta2,f[i][j-1][1]+(B[j].x-B[j-1].x)*delta2);}printf("%.3lf\n",(double)(tot-min(f[n][m][0],f[n][m][1]))/1000.0); }int main() {_init();_solve();return 0; }
總結(jié)
以上是生活随笔為你收集整理的【SDOI2008】Sue的小球的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux centos7 增加ipv6
- 下一篇: Excel 快捷键大全