POJ1661----Help_Jimmy
小白这道题想了好久,下面是我的思路以及代码
为了方便看懂程序进行到哪里,添加了标记来输出,
相信你最终也能看懂!
输入数据:
1------------------------------>一组测试数据
3 8 17 20------------------->三个台阶,初始位置(8,17),一次最大下落20
0 10 8----------------------->left = 0, right = 10, height = 8
0 10 13--------------------->left = 0, right = 10, height = 13
4 14 3----------------------->left = 4, right = 14, height = 3
输出:
23---------------------------->共走了23步
思路:
- 将台阶按照height排序,矮的在下,地面最矮,为第0个.
- 最初的(8,17)需要判断第一次落在哪个台阶上
- 已知落在哪个台阶和自身坐标—>找下一级台阶—>从左边还是右边落到台阶上时间短—>下落—>重新已知在哪个台阶和自身坐标(其中Y = 所在台阶的高,X为上一次台阶左/右边缘)
第一步:输入数据并将台阶排序
#include<bits/stdc++.h>
#define MaxSize 101
using namespace std;
int MAX;
int num_ban;
struct Board{
int left,right,height;
}Ban[MaxSize];
bool compare(Board A,Board B){ //按照高度从小到大排序
return (A.height < B.height);
}
int main()
{
int X,Y;
int test_num;
cin>>test_num;
while(test_num -- ){
cin>>num_ban>>X>>Y>>MAX;
Ban[0].left = -1000000;Ban[0].right = 1000000;Ban[0].height = 0;
for(int i = 1;i <= num_ban;i++){
cin>>Ban[i].left>>Ban[i].right>>Ban[i].height;
}
sort(Ban+1,Ban+num_ban+1,compare);
// cout<<Ban[1].height<<" "<<Ban[1].left<<" "<<Ban[1].right;
cout<<MinTime(X,Y);
}
return 0;
}
第二步:判断第一次落在哪,并return min(cal(X,i,0),cal(X,i,1))+y
int MinTime(int X,int Y){
// cout<<"in MinTime\n";
for(int i = num_ban;i >= 0;i--){
if(X>=Ban[i].left&&X<=Ban[i].right&&(Y-Ban[i].height)<=MAX){
// cout<<"kth="<<i<<" X="<<X<<" Y="<<Y<<endl;
int y = Y - Ban[i].height;
return min(cal(X,i,0),cal(X,i,1))+y;
}
}
// cout<<"out of MinTime\n";
}
第三步:判断可否走左/右,并返回步数
int cal(int X,int kth,int leftorright){ //0左1右
// cout<<"in cal---------------------\n";
int Y = Ban[kth].height;
// cout<<"kth="<<kth<<" X="<<X<<" Y="<<Y<<endl;
if(leftorright == 0){
// cout<<"左面\n";
int left_next = -1; //判断可否走左面
if(kth == 1) return X-Ban[kth].left+Ban[kth].height;
else if(kth == 0) return 0;
else{
for(int i = kth-1;i >= 0;i--){
if(Ban[kth].left>=Ban[i].left&&Ban[kth].left<=Ban[i].right&&(Y-Ban[i].height)<=MAX){
left_next = i;
break;
}
}
if(left_next == -1) return 100000;
else{
int dx = X-Ban[kth].left;
int dy = Ban[kth].height-Ban[left_next].height;
return dx+dy+min(cal(Ban[kth].left,left_next,0),cal(Ban[kth].left,left_next,1));
}
}
}
else{
// cout<<"右面\n";
int right_next = -1;
if(kth == 1) return Ban[kth].right-X+Ban[kth].height;
else if(kth == 0) return 0;
else {
for(int i = kth-1;i >= 0;i--){
if(Ban[kth].right>=Ban[i].left&&Ban[kth].right<=Ban[i].right&&(Y-Ban[i].height)<=MAX){
right_next = i;
break;
}
}
if(right_next == -1) return 100000; //如果走右面不满足条件
else{
int dx = Ban[kth].right-X;
int dy = Ban[kth].height-Ban[right_next].height;
return dx+dy+min(cal(Ban[kth].right,right_next,0),cal(Ban[kth].right,right_next,1));
}
}
}
}
小白觉得这道题还是挺复杂的,大家一定要动手做一下啊!