Help Jimmy
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 11621 | Accepted: 3827 |
Description
场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。
Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。
设计一个程序,计算Jimmy到底地面时可能的最早时间。
Input
Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。
Output
Sample Input
1 3 8 17 20 0 10 8 0 10 13 4 14 3
Sample Output
23
Source
dp[i][0]=min(dp[i][0],dp[j][0]+abs(a[j].X1-a[i].X1)+a[i].H-a[j].H);
dp[i][0]=min(dp[i][0],dp[j][1]+abs(a[j].X2-a[i].X1)+a[i].H-a[j].H);
dp[i][1]=min(dp[i][1],dp[j][0]+abs(a[j].X1-a[i].X2)+a[i].H-a[j].H);
dp[i][1]=min(dp[i][1],dp[j][1]+abs(a[j].X2-a[i].X2)+a[i].H-a[j].H);
当然,前提是j块木板的高度差不能超过MAX且第i块木板落下到第j块木板(这个可以预处理)
这个题要倒着做!倒着做!
开始正着做了一遍,把discuss中的数据测光了也是对的,莫名其妙WA了一小时 TAT
后来花了10分钟重写了一个正着做的就一遍AC了……
此题需要注意的细节:
①MEMSET inf
②落到板子的边缘也算落在板子上
③在高度允许情况下可以直接落到地上
④abs
是否感觉有些反人类思维呢?听说最短路可以过TAT
代码
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<stack> #include<vector> #include<algorithm> //#include<cmath> using namespace std; const int INF = 9999999; #define LL long long inline int read(){ int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } int N,X,Y,MAX; int T; struct data{ int X1,X2,H; }a[1001]; int dp[1001][2]; int down[1001][2]; int fir; bool flag=false; bool cmp(data a,data b){ return a.H>b.H; } void pre(){//预处理 sort(a+1,a+N+1,cmp);//sort一定要加 bool flag1=false,flag2=false; for(int i=1;i<=N;i++){//记录第i块板子左/右落下会落到哪里 flag1=false,flag2=false; for(int j=i+1;j<=N;j++){ if(flag1&&flag2) break; if(a[i].H>a[j].H){ if(a[j].X1<=a[i].X1&&a[j].X2>=a[i].X1&&!flag1) down[i][0]=j,flag1=true; if(a[j].X2>=a[i].X2&&a[j].X1<=a[i].X2&&!flag2) down[i][1]=j,flag2=true; } } if(!flag1) down[i][0]=N+1;//N+1板子为地面 if(!flag2) down[i][1]=N+1; } a[N+1].H=0;a[N+1].X1=-INF,a[N+1].X2=INF; for(int i=1;i<=N+1;i++){//预处理从初始点落下会落到哪里 if(Y-a[i].H<=MAX) if(a[i].X1<=X&&a[i].X2>=X){ fir=i; break; } } if(fir==N+1){ printf("%d ",Y);//可以直接落到地面上,直接输出 flag=true; } return ; } int main(){ T=read(); while(T--){ flag=false; N=read(),X=read(),Y=read(),MAX=read(); for(int i=1;i<=N;i++){ a[i].X1=read(); a[i].X2=read(); a[i].H=read(); } memset(dp,INF,sizeof(dp));//memset pre(); if(flag) continue; dp[N+1][0]=0; dp[N+1][1]=0; dp[N][1]=dp[N][0]=a[N].H; for(int i=N-1;i>=fir;i--){ for(int j=i+1;j<=N+1;j++){ if(abs(a[i].H-a[j].H)>MAX) break;//如果高度差已经大于MAX直接退出 if(down[i][0]==j){//dp if(j!=N+1){ dp[i][0]=min(dp[i][0],dp[j][0]+abs(a[j].X1-a[i].X1)+a[i].H-a[j].H); dp[i][0]=min(dp[i][0],dp[j][1]+abs(a[j].X2-a[i].X1)+a[i].H-a[j].H); } else dp[i][0]=min(dp[i][0],a[i].H); } if(down[i][1]==j){ if(j!=N+1){ dp[i][1]=min(dp[i][1],dp[j][0]+abs(a[j].X1-a[i].X2)+a[i].H-a[j].H); dp[i][1]=min(dp[i][1],dp[j][1]+abs(a[j].X2-a[i].X2)+a[i].H-a[j].H); } else dp[i][1]=min(dp[i][1],a[i].H); } } } printf("%d ",min(dp[fir][0]+abs(a[fir].X1-X)+abs(Y-a[fir].H),dp[fir][1]+abs(a[fir].X2-X)+abs(Y-a[fir].H))); } return 0; }