hdu 2059(dp)
生活随笔
收集整理的這篇文章主要介紹了
hdu 2059(dp)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
? ??龜兔賽跑
Time Limit: 1000/1000 MS (Java/Others)????Memory Limit: 32768/32768 K (Java/Others)Problem Description 據(jù)說在很久很久以前,可憐的兔子經(jīng)歷了人生中最大的打擊——賽跑輸給烏龜后,心中郁悶,發(fā)誓要報仇雪恨,于是躲進(jìn)了杭州下沙某農(nóng)業(yè)園臥薪嘗膽潛心修煉,終于練成了絕技,能夠毫不休息得以恒定的速度(VR m/s)一直跑。兔子一直想找機(jī)會好好得教訓(xùn)一下烏龜,以雪前恥。
最近正值HDU舉辦50周年校慶,社會各大名流齊聚下沙,兔子也趁此機(jī)會向烏龜發(fā)起挑戰(zhàn)。雖然烏龜深知獲勝希望不大,不過迫于輿論壓力,只能接受挑戰(zhàn)。
比賽是設(shè)在一條筆直的道路上,長度為L米,規(guī)則很簡單,誰先到達(dá)終點誰就算獲勝。
無奈烏龜自從上次獲勝以后,成了名龜,被一些八卦雜志稱為“動物界的劉翔”,廣告不斷,手頭也有了不少積蓄。為了能夠再贏兔子,烏龜不惜花下血本買了最先進(jìn)的武器——“"小飛鴿"牌電動車。這輛車在有電的情況下能夠以VT1 m/s的速度“飛馳”,可惜電池容量有限,每次充滿電最多只能行駛C米的距離,以后就只能用腳來蹬了,烏龜用腳蹬時的速度為VT2 m/s。更過分的是,烏龜竟然在跑道上修建了很多很多(N個)的供電站,供自己給電動車充電。其中,每次充電需要花費T秒鐘的時間。當(dāng)然,烏龜經(jīng)過一個充電站的時候可以選擇去或不去充電。
比賽馬上開始了,兔子和帶著充滿電的電動車的烏龜并列站在起跑線上。你的任務(wù)就是寫個程序,判斷烏龜用最佳的方案進(jìn)軍時,能不能贏了一直以恒定速度奔跑的兔子。
Input 本題目包含多組測試,請?zhí)幚淼轿募Y(jié)束。每個測試包括四行:
第一行是一個整數(shù)L代表跑道的總長度
第二行包含三個整數(shù)N,C,T,分別表示充電站的個數(shù),電動車沖滿電以后能行駛的距離以及每次充電所需要的時間
第三行也是三個整數(shù)VR,VT1,VT2,分別表示兔子跑步的速度,烏龜開電動車的速度,烏龜腳蹬電動車的速度
第四行包含了N(N<=100)個整數(shù)p1,p2...pn,分別表示各個充電站離跑道起點的距離,其中0<p1<p2<...<pn<L
其中每個數(shù)都在32位整型范圍之內(nèi)。
Output 當(dāng)烏龜有可能贏的時候輸出一行 “What a pity rabbit!"。否則輸出一行"Good job,rabbit!";
題目數(shù)據(jù)保證不會出現(xiàn)烏龜和兔子同時到達(dá)的情況。
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!
首先是講一下我自己的思路:定義狀態(tài)dp[i][j]表示為跑到第i米,且當(dāng)前電量還能跑j米,所需要的時間,那么0<=j<=C,那么狀態(tài)方程就很容易得到:dp[i][j] = min(dp[i+1][j-1],dp[i][j] + 1/vt1) (j > 0),如果這個地方是一個充電站,那么還講需要一個方程:dp[i+1][C-1] = min(dp[i+1][C-1],dp[i][j] + T + 1/vt1);當(dāng)然,如果j==0時,那么只能夠腳踏了。 這個思路確實是正確的,但是超時了。主要的地方還是沒有理解題目的意思,因為每一個充電站的距離是一定的,那么這一段距離肯定是C的距離是以vt1的速度,剩下的距離是以vt2的速度,所以以充電站為狀態(tài)進(jìn)行轉(zhuǎn)移的話,那么可以節(jié)省很多次循環(huán)的時間。
TLE: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;const int maxn = 10000; const int inf = 0x3f3f3f3f; int l,n,c,t; int vr,vt1,vt2,pos[110]; double dp[maxn][110];bool find(int len) {int l = 1, r = n;int mid;while(l <= r){mid = (l + r) >> 1;if(pos[mid] == len) return true;else if(pos[mid] > len)r = mid - 1;else l = mid + 1;}return false; }int main() { while(scanf("%d",&l)!=EOF){scanf("%d%d%d",&n,&c,&t);scanf("%d%d%d",&vr,&vt1,&vt2);for(int i = 1; i <= n; i++)scanf("%d",&pos[i]);double rt = l*1.0/vr; //兔子所需時間for(int i = 0; i <= l; i++)for(int j = 0; j <= c; j++)dp[i][j] = inf;dp[0][c] = 0;for(int i = 0; i < l; i++)for(int j = 0; j <= c; j++){if(dp[i][j] < inf) //當(dāng)前狀態(tài)合法{if(j == 0){dp[i+1][j] = min(dp[i+1][j],dp[i][j] + 1.0 / vt2);}else {dp[i+1][j-1] = min(dp[i+1][j-1],dp[i][j] + 1.0 / vt1);}if(find(i) == true) //該位置是一個充電站{dp[i+1][c-1] = min(dp[i+1][c-1],dp[i][j] + t + 1.0 / vt1);}}}bool flag = false;for(int i = 0; i <= c; i++){if(dp[l][i] < rt){flag = true;break;}}if(flag) printf("What a pity rabbit!\n");else printf("Good job,rabbit!\n");}return 0; }
AC: 思路:dp[i]:記錄到站點i的最短時間,從0 - (i-1) 判斷確定加油后到i的時間,因為到i點肯定是由0-(i-1)中的某一點加了油后不再加油直接到達(dá)i點最優(yōu)(即肯定有一個最后加油點)??赡軙幸蓡?#xff0c;如果之前到某一點 j 時還有余量,那再加油判斷是不是會有問題呢?其實不會,如果到j(luò)你不加油,那肯定是之前的某k點加油了,而那點dp[k]已計算過了,所以不再考慮j點不加油的情況,所以一直dp下來即可求出到達(dá)終點的最短時間。
#include<iostream> #include<cstdio> using namespace std;const int inf = 0x3f3f3f3f; int main() { int L,C,T;int VR,VT1,VT2;int p[105],N;double dp[105];while(cin>>L){cin>>N>>C>>T;cin>>VR>>VT1>>VT2;p[0] = 0;for(int i = 1; i <= N; i++)cin>>p[i];p[N+1] = L;dp[0] = 0;for(int i = 1; i <= N+1; i++){double MIN = inf;double tmp;for(int j = 0; j < i; j++){int l = p[i] - p[j];if(l < C)tmp = l*1.0/VT1; elsetmp = C*1.0/VT1+(l-C)*1.0/VT2; if(j != 0)tmp += T;tmp += dp[j];if(tmp < MIN)MIN = tmp;}dp[i] = MIN;}printf(dp[N+1]>(L*1.0/VR)?"Good job,rabbit!\n":"What a pity rabbit!\n"); }return 0; }
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的hdu 2059(dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JEECG社区招募新人啦
- 下一篇: hdu 4529(状态dp)