您的位置:首页 > 其它

(hdu step 4.2.4)A strange lift(求从起点到终点的最小步数,限制条件是:在一维的情况下)

2015-02-17 17:44 543 查看
题目:

A strange lift

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 709 Accepted Submission(s): 348
 
[align=left]Problem Description[/align]There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can't go up high than N,and can't go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you'll go up to the 4 th floor,and if you press the button "DOWN", the lift can't do it, because it can't go down to the -2 th floor,as you know ,the -2 th floor isn't exist.
Here comes the problem: when you is on floor A,and you want to go to floor B,how many times at least he havt to press the button "UP" or "DOWN"? 
[align=left]Input[/align]The input consists of several test cases.,Each test case contains two lines.
The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,....kn.
A single 0 indicate the end of the input. 
[align=left]Output[/align]For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can't reach floor B,printf "-1". 
[align=left]Sample Input[/align]
5 1 5
3 3 1 2 5
0
 
[align=left]Sample Output[/align]
3
 
 
 
[align=left]Recommend[/align]8600
题目分析:
                广搜题。在一维的情况下,求从起点到终点的最小步数。这道题有一下特点:
1)没有涉及障碍物的概念。也就是说每一点理论上都可以到达。在做搜索的题目的时候,一般都会有map[][]矩阵和vis[][]。前者用于存储整张地图的信息,如那些是路,那些事障碍物,公主(终点)在哪里,你(起点)在哪里。后者用于标记到达某一节点是的最小步数(个人习惯,这里的vis[][]是int类型的)。因为这道题中没有障碍物的概念,所以我们其实并不需要开一个map[][]数数组。
2)这道题是一维的。所以开vis数组的时候开到一维的就可以了。
3)每一点的步长不一样。之前我们接触的题目,大部分都是只能到达相邻节点,而这道题中,我们身处第一层的时候,有可能我们就只能直接到第三层,而不是到第二层。其实这也是由这道题中的“一维”的这个概念所限制的。你想想,如果在一位的情况下,每一节点只能到达相邻节点,那么在第一层就只能去到第二层。那么样例中所说的从第一层到第5层就之恩能够使一层一层的上了,就不是所谓的搜索题目了,因为在这种情况下按(5-1)次按钮就能到达指定楼层。

需要注意的是,从某一楼层出发以后,很可能不再回到该楼层,否则就死循环了。

代码如下:
/*
* d.cpp
*
* Created on: 2015年2月17日
* Author: Administrator
*/

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

const int maxn = 205;
const int inf = 999999;

int vis[maxn];//用于标记访问有一个节点的最小步数
int dir[maxn];//某一个节点移到下一个节点的步长

int n;//节点的个数
int start;//起点
int end;//终点

struct Node{//节点
int floor;//用于标记现在位于第几层
int step;//到达现在这个位置所需要的步数

friend bool operator<(Node a,Node b){//用于实现在在优先队列中从小到大排序
return a.step > b.step;
}
};

/**
* 判断下一届点是否合法
*/
bool check(int floor){
if(floor < 0 || floor >= n){//判断当前楼层是否合法
return false;
}

return true;//表示当前楼层合法
}

int bfs(){
priority_queue<Node> q;

//初始化根节点
Node root;
root.floor = start;
root.step = 0;

Node k;

q.push(root);//根节点入队
while(!q.empty()){//如果队列非空
Node a = q.top();//每次去除対首元素
q.pop();

if(a.floor == end){//如果已经达到终点
return a.step;//返回到达终点所需要的步数
}

//第一个方向
k.floor = a.floor + dir[a.floor];//计算下一节点的位置
if(check(k.floor) == true){//如果下一节点的位置合法
k.step = a.step+1;//计算到达下一节点所需要的步数

if(vis[k.floor] > k.step){//如果之前到达目标节点所需要的步数>目前到达目标节点所需要的步数
vis[k.floor] = k.step;//更新到达当前节点所需要的最小步数
q.push(k);//将该元素入队
}
}

//第二个方向
k.floor = a.floor - dir[a.floor];
if(check(k.floor) == true){
k.step = a.step+1;
if(vis[k.floor] > k.step){
vis[k.floor] = k.step;
q.push(k);
}
}
}

return -1;//表示没有到达终点
}

int main(){
while(scanf("%d",&n)!=EOF,n){
scanf("%d%d",&start,&end);

start -= 1;//这里需要注意一下.位置我这里是从0来时算的
end -= 1;

int i;
for(i = 0 ; i < n ; ++i){
scanf("%d",&dir[i]);//初始化每一楼层的步长
}

memset(vis,inf,sizeof(vis));//初始化到达每一节点的最小步数

printf("%d\n",bfs());
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: