poj1661 记忆化搜索

这题要敢想敢做

dp[i][0]表示从上数第i层左边到达地面的时间

dp[i][1]同理

//poj1661 //题目为是男人就下100层 //dp,只要你敢想! #include <iostream> #include <algorithm> #include <cmath> using namespace std; struct data { int x1,x2,y; }a[1010]; int dp[1010][2]; bool v[1010]; int n,maxx; bool cmp(data a,data b) { return a.y>b.y; } void find(int i) { int x,j; if (v[i]) return; v[i]=true; dp[i][0]=100000; x=a[i].x1; bool flag=false; for (j=i+1;j<=n;j++) if (a[j].x1<=x && x<=a[j].x2) { flag=true; if (a[i].y-a[j].y>maxx) dp[i][0]=-1; else { find(j); if (dp[j][0]==-1 && dp[j][1]==-1) dp[i][0]=-1; if (dp[j][0]!=-1) dp[i][0]=min(dp[i][0],dp[j][0]+abs(a[j].x1-a[i].x1)+a[i].y-a[j].y); if (dp[j][1]!=-1) dp[i][0]=min(dp[i][0],dp[j][1]+abs(a[j].x2-a[i].x1)+a[i].y-a[j].y); } break; } if (!flag) { if (a[i].y<=maxx) dp[i][0]=a[i].y; else dp[i][0]=-1; } dp[i][1]=100000; x=a[i].x2; flag=false; for (j=i+1;j<=n;j++) if (a[j].x1<=x && x<=a[j].x2) { flag=true; if (a[i].y-a[j].y>maxx) dp[i][1]=-1; else { find(j); if (dp[j][0]==-1 && dp[j][1]==-1) dp[i][1]=-1; if (dp[j][0]!=-1) dp[i][1]=min(dp[i][1],dp[j][0]+abs(a[j].x1-a[i].x2)+a[i].y-a[j].y); if (dp[j][1]!=-1) dp[i][1]=min(dp[i][1],dp[j][1]+abs(a[j].x2-a[i].x2)+a[i].y-a[j].y); } break; } if (!flag) { if (a[i].y<=maxx) dp[i][1]=a[i].y; else dp[i][1]=-1; } } int main() { int t,x,y,ans,i,j; cin >> t; while (t--) { cin >> n >> x >> y >> maxx; for (i=1;i<=n;i++) cin >> a[i].x1 >> a[i].x2 >> a[i].y; sort(a+1,a+n+1,cmp); memset(dp,0,sizeof(dp)); memset(v,false,sizeof(v)); ans=100000; bool flag=false; for (j=1;j<=n;j++) if (a[j].x1<=x && x<=a[j].x2) { flag=true; find(j); if (dp[j][0]!=-1) ans=min(ans,dp[j][0]+abs(a[j].x1-x)+y-a[j].y); if (dp[j][1]!=-1) ans=min(ans,dp[j][1]+abs(a[j].x2-x)+y-a[j].y); break; } if (!flag) ans=y; cout << ans << endl; } //system("pause"); return 0; }

你可能感兴趣的:(poj1661 记忆化搜索)