【POJ - 1661】Help Jimmy(记忆化搜索,dp)
題干:
Help Jimmy" 是在下圖所示的場(chǎng)景上完成的游戲。?
?
場(chǎng)景中包括多個(gè)長(zhǎng)度和高度各不相同的平臺(tái)。地面是最低的平臺(tái),高度為零,長(zhǎng)度無(wú)限。?
Jimmy老鼠在時(shí)刻0從高于所有平臺(tái)的某處開(kāi)始下落,它的下落速度始終為1米/秒。當(dāng)Jimmy落到某個(gè)平臺(tái)上時(shí),游戲者選擇讓它向左還是向右跑,它跑動(dòng)的速度也是1米/秒。當(dāng)Jimmy跑到平臺(tái)的邊緣時(shí),開(kāi)始繼續(xù)下落。Jimmy每次下落的高度不能超過(guò)MAX米,不然就會(huì)摔死,游戲也會(huì)結(jié)束。?
設(shè)計(jì)一個(gè)程序,計(jì)算Jimmy到底地面時(shí)可能的最早時(shí)間。?
Input
第一行是測(cè)試數(shù)據(jù)的組數(shù)t(0 <= t <= 20)。每組測(cè)試數(shù)據(jù)的第一行是四個(gè)整數(shù)N,X,Y,MAX,用空格分隔。N是平臺(tái)的數(shù)目(不包括地面),X和Y是Jimmy開(kāi)始下落的位置的橫豎坐標(biāo),MAX是一次下落的最大高度。接下來(lái)的N行每行描述一個(gè)平臺(tái),包括三個(gè)整數(shù),X1[i],X2[i]和H[i]。H[i]表示平臺(tái)的高度,X1[i]和X2[i]表示平臺(tái)左右端點(diǎn)的橫坐標(biāo)。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所有坐標(biāo)的單位都是米。?
Jimmy的大小和平臺(tái)的厚度均忽略不計(jì)。如果Jimmy恰好落在某個(gè)平臺(tái)的邊緣,被視為落在平臺(tái)上。所有的平臺(tái)均不重疊或相連。測(cè)試數(shù)據(jù)保證問(wèn)題一定有解。?
Output
對(duì)輸入的每組測(cè)試數(shù)據(jù),輸出一個(gè)整數(shù),Jimmy到底地面時(shí)可能的最早時(shí)間。
?
AC代碼1:
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; const int INF = 0x3f3f3f3f; int n,x,y,maxx; int dp[1005][2];//fg=0代表左邊,fg=1代表右邊 struct Node {int l,r,h; } node[1005]; bool cmp(const Node & a,const Node & b) {return a.h < b.h; } int dfs(int cur,int fg) {if(cur == 1) return 0;if(dp[cur][fg] != -1) return dp[cur][fg];if(cur == 1) {return 0;}int ans = INF;if(dp[cur][fg] != -1) {return dp[cur][fg];}int temp = cur; for(int i = cur-1; i>=1; i--) {temp=i;if(node[cur].h - node[i].h > maxx) break;if(fg==0) {if(node[i].l <= node[cur].l && node[i].r >= node[cur].l) {ans = min(dfs(i,0)+node[cur].l-node[i].l,dfs(i,1) +node[i].r-node[cur].l );break;}} else {if(node[i].r >= node[cur].r && node[i].l <= node[cur].r) {ans = min(dfs(i,0)+node[cur].r-node[i].l,dfs(i,1)+node[i].r-node[cur].r);break;}}}if(ans == INF) {if(node[cur].h <= maxx) return dp[cur][fg] = 0;else return dp[cur][fg] = ans;}else return dp[cur][fg] = ans; } int main() {int t;cin>>t;while(t--) {scanf("%d%d%d%d",&n,&x,&y,&maxx);memset(dp,-1,sizeof (dp));for(int i = 1; i<=n; i++) {scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].h);}sort(node+1,node+n+1,cmp);int ok=n+1; // node[ok].h = y;node[ok].l=node[ok].r=x;for(int i = n; i>=1; i--) {if(node[i].r >= x && node[i].l <= x) {ok=i;break;}}if(ok == n+1) {printf("%d\n",y);}else {int ans = min(dfs(ok,1) + node[ok].r-x,dfs(ok,0) + x-node[ok].l) + y; // int ans = min(dfs(ok,1),dfs(ok,0)) + y;printf("%d\n",ans);}} return 0 ;} //1 //1 //2 3 //100 //5 6 1AC代碼2:
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; const int INF = 0x3f3f3f3f; int n,x,y,maxx; int dp[1005][2];//fg=0代表左邊,fg=1代表右邊 struct Node {int l,r,h; } node[1005]; bool cmp(const Node & a,const Node & b) {return a.h < b.h; } int dfs(int cur,int fg) {if(cur == 1) return 0;if(dp[cur][fg] != -1) return dp[cur][fg]; // int minn = 0x3f3f3f3f,flag=0;//0左 1右 // int temp=cur;int ans = INF;int temp = cur; for(int i = cur-1; i>=1; i--) {temp=i;if(node[cur].h - node[i].h > maxx) break;if(fg==0) {if(node[i].l <= node[cur].l && node[i].r >= node[cur].l) {ans = min(dfs(i,0)+node[cur].l-node[i].l,dfs(i,1) +node[i].r-node[cur].l );break;}} else {if(node[i].r >= node[cur].r && node[i].l <= node[cur].r) {ans = min(dfs(i,0)+node[cur].r-node[i].l,dfs(i,1)+node[i].r-node[cur].r);break;}}}if(ans == INF) {if(node[cur].h <= maxx) return dp[cur][fg] = 0;else return dp[cur][fg] = ans;}else return dp[cur][fg] = ans; // if(ans == INF) { // if(temp == 1) { // if(node[cur].h > maxx) return dp[cur][fg] = ans; // else return dp[cur][fg] = 0; // } // return dp[cur][fg] = ans; // } // else return dp[cur][fg] = ans; } int main() {int t;cin>>t;while(t--) {scanf("%d%d%d%d",&n,&x,&y,&maxx);memset(dp,-1,sizeof (dp));for(int i = 1; i<=n; i++) {scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].h);}sort(node+1,node+n+1,cmp);int ok=n+1;node[ok].h = y;node[ok].l=node[ok].r=x; // for(int i = n; i>=1; i--) { // if(node[i].r >= x && node[i].l <= x) { // ok=i;break; // } // } // int ans = min(dfs(ok,1) + node[ok].r-x,dfs(ok,0) + x-node[ok].l) + y;int ans = min(dfs(ok,1),dfs(ok,0)) + y;printf("%d\n",ans);} return 0 ;}錯(cuò)誤代碼:
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; int n,x,y,maxx; int dp[1005]; struct Node {int l,r,h; } node[1005]; bool cmp(const Node & a,const Node & b) {return a.h < b.h; } int dfs(int cur,int curx,int curh) {if(curh == 0) return 0;if(cur < 0) return 0;if(dp[cur] != -1) return dp[cur];int minn = 0x3f3f3f3f;for(int i = cur-1; i>=1; i--) {if(curh - node[i].h > maxx) break;if(node[i].l <= node[cur].l) minn = min(minn,dfs(i,node[cur].l,node[i].h)+node[cur].l-curx);if(node[i].r >= node[cur].r) minn = min(minn,dfs(i,node[cur].r,node[i].h)+node[cur].r-curx);}return dp[cur] = minn; } int main() {int t;cin>>t;while(t--) {scanf("%d%d%d%d",&n,&x,&y,&maxx);memset(dp,-1,sizeof (dp));for(int i = 1; i<=n; i++) {scanf("%d%d%d",&node[i].l,&node[i].r,&node[i].h);}sort(node+1,node+n+1,cmp);printf("%d\n",dfs(n,x,node[n].h));} // 18653293769return 0 ;}總結(jié):
? ?幾個(gè)地方是真的坑,首先這個(gè)錯(cuò)誤代碼,記憶化搜素的設(shè)計(jì)狀態(tài)我就沒(méi)搞明白(因?yàn)楹髞?lái)我通過(guò)觀察發(fā)現(xiàn)一維dp表示不了所有狀態(tài)),于是dfs中亂設(shè)了一堆參數(shù),結(jié)果顯然都沒(méi)用。
? ?其二,函數(shù)內(nèi)部,顯然要break,不能不加break,因?yàn)橛猩弦粋€(gè)臺(tái)子擋住了,后面即使有符合的,也不能跳上去了,所以要break。
? ?其三,要處理好到地面的那一步,一定是直接跳過(guò)去的(也就是 一定ans==INF),所以return的時(shí)候不能直接retrun dp[cur][fg] = ans;而應(yīng)該判斷是否ans==INF 如果等于的話,也就說(shuō)明是到地面了,要dp[cur][fg] = 0;才可以。
? ?其四,有個(gè)處理技巧,讓出發(fā)點(diǎn)當(dāng)成一個(gè)新的平臺(tái),這樣直接統(tǒng)一形式就可以了。不然的話,就跟AC代碼1一樣,先判斷是否從出發(fā)點(diǎn)可以直接落到地面上,特判一下這個(gè)條件才可以。
? 其五,有個(gè)技巧,就是高度都最后統(tǒng)一算,直接+y就可以了,這樣減少了代碼出錯(cuò)概率。
? 其六,遞歸函數(shù)中的狀態(tài)轉(zhuǎn)移要想清楚,到底是由哪些狀態(tài)轉(zhuǎn)移而來(lái),或者想,可以轉(zhuǎn)移到哪些狀態(tài)去。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的【POJ - 1661】Help Jimmy(记忆化搜索,dp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: RadioSvr.EXE - Radio
- 下一篇: 【POJ - 2909 】Goldbac