1661】Help Jimmy(記憶化搜素,dp)
阿新 • • 發佈:2018-12-11
題幹:
解題報告:
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 1
AC程式碼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 ; }
錯誤程式碼:
#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)); } // 18653293769 return 0 ; }
總結:
幾個地方是真的坑,首先這個錯誤程式碼,記憶化搜素的設計狀態我就沒搞明白(因為後來我通過觀察發現一維dp表示不了所有狀態),於是dfs中亂設了一堆引數,結果顯然都沒用。
其二,函式內部,顯然要break,不能不加break,因為有上一個臺子擋住了,後面即使有符合的,也不能跳上去了,所以要break。
其三,要處理好到地面的那一步,一定是直接跳過去的(也就是 一定ans==INF),所以return的時候不能直接retrun dp[cur][fg] = ans;而應該判斷是否ans==INF 如果等於的話,也就說明是到地面了,要dp[cur][fg] = 0;才可以。
其四,有個處理技巧,讓出發點當成一個新的平臺,這樣直接統一形式就可以了。不然的話,就跟AC程式碼1一樣,先判斷是否從出發點可以直接落到地面上,特判一下這個條件才可以。
其五,有個技巧,就是高度都最後統一算,直接+y就可以了,這樣減少了程式碼出錯概率。
其六,遞迴函式中的狀態轉移要想清楚,到底是由哪些狀態轉移而來,或者想,可以轉移到哪些狀態去。