1. 程式人生 > >HDU 2059 龜兔賽跑(超級經典的線性DP,找合適的j,使得每個i的狀態都是最好的)

HDU 2059 龜兔賽跑(超級經典的線性DP,找合適的j,使得每個i的狀態都是最好的)

龜兔賽跑 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status

Description

據說在很久很久以前,可憐的兔子經歷了人生中最大的打擊——賽跑輸給烏龜後,心中鬱悶,發誓要報仇雪恨,於是躲進了杭州下沙某農業園臥薪嚐膽潛心修煉,終於練成了絕技,能夠毫不休息得以恆定的速度(VR m/s)一直跑。兔子一直想找機會好好得教訓一下烏龜,以雪前恥。
最近正值HDU舉辦50週年校慶,社會各大名流齊聚下沙,兔子也趁此機會向烏龜發起挑戰。雖然烏龜深知獲勝希望不大,不過迫於輿論壓力,只能接受挑戰。
比賽是設在一條筆直的道路上,長度為L米,規則很簡單,誰先到達終點誰就算獲勝。
無奈烏龜自從上次獲勝以後,成了名龜,被一些八卦雜誌稱為“動物界的劉翔”,廣告不斷,手頭也有了不少積蓄。為了能夠再贏兔子,烏龜不惜花下血本買了最先進的武器——“"小飛鴿"牌電動車。這輛車在有電的情況下能夠以VT1 m/s的速度“飛馳”,可惜電池容量有限,每次充滿電最多隻能行駛C米的距離,以後就只能用腳來蹬了,烏龜用腳蹬時的速度為VT2 m/s。更過分的是,烏龜竟然在跑道上修建了很多很多(N個)的供電站,供自己給電動車充電。其中,每次充電需要花費T秒鐘的時間。當然,烏龜經過一個充電站的時候可以選擇去或不去充電。
比賽馬上開始了,兔子和帶著充滿電的電動車的烏龜並列站在起跑線上。你的任務就是寫個程式,判斷烏龜用最佳的方案進軍時,能不能贏了一直以恆定速度奔跑的兔子。  

Input

本題目包含多組測試,請處理到檔案結束。每個測試包括四行:
第一行是一個整數L代表跑道的總長度
第二行包含三個整數N,C,T,分別表示充電站的個數,電動車衝滿電以後能行駛的距離以及每次充電所需要的時間
第三行也是三個整數VR,VT1,VT2,分別表示兔子跑步的速度,烏龜開電動車的速度,烏龜腳蹬電動車的速度
第四行包含了N(N<=100)個整數p1,p2...pn,分別表示各個充電站離跑道起點的距離,其中0<p1<p2<...<pn<L
其中每個數都在32位整型範圍之內。
 

Output

當烏龜有可能贏的時候輸出一行 “What a pity rabbit!"。否則輸出一行"Good job,rabbit!";
題目資料保證不會出現烏龜和兔子同時到達的情況。  

Sample Input

100 3 20 5 5 8 2 10 40 60 100 3 60 5 5 8 2 10 40 60  

Sample Output

Good job,rabbit! What a pity rabbit!  
#include<stdio.h>
#include
<iostream> #include<math.h> #include<string.h> #include<set> #include<map> #include<list> #include<algorithm> using namespace std; typedef long long LL; int mon1[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int mon2[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31}; int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}}; #define max_v 105 #define INF 9999999999 int a[max_v]; double dp[max_v];//dp[i] 起點到第i個充電樁需要的最小時間 //dp[i]=min(dp[j]+time); j屬於1到i-1 //核心思想:現在要到第i個充電樁去,所以在1到i-1的這些充電樁中,選擇一個合適的充電樁,使得j到i的時間最少 //就是選擇一個狀態最好的j,使得到每個充電樁i的狀態都是最好的! int main() { int L,N,C,T; double VR,VT1,VT2; while(~scanf("%d",&L)) { scanf("%d %d %d",&N,&C,&T); scanf("%lf %lf %lf",&VR,&VT1,&VT2); for(int i=1;i<=N;i++) scanf("%d",&a[i]); //將終點也看作一個充電站 a[N+1]=L; //dp初始化,因求最小值,所以dp無窮大 //特殊初始化:dp[0]=0 for(int i=0;i<=N;i++) dp[i]=INF; dp[0]=0; for(int i=1;i<=N+1;i++)//從第一個充電站到最後一個充電樁,即終點 { double Min=INF; for(int j=0;j<i;j++)//從1到i這段的充電站中選擇一個最好的j充電站充電,使得花費時間最少 { double time=0; if(a[i]-a[j]<=C)//不需要蹬 { time+=(a[i]-a[j])*1.0/VT1;//騎行時間 }else//需要蹬 { time+=C*1.0/VT1+(a[i]-a[j]-C)*1.0/VT2;//騎行時間+蹬的時間 } if(j)//起點不充電 time+=T; Min=min(Min,dp[j]+time*1.0); } dp[i]=Min; } //兔子花費時間 double TR=L*1.0/VR; if(dp[N+1]<TR) printf("What a pity rabbit!\n"); else printf("Good job,rabbit!\n"); } return 0; }