奇怪的电梯广搜做法~
一、题目描述:
一种很奇怪的电梯,大楼的每一层楼都可以停电梯,而且第 i 层楼(1 ≤ i ≤ N)上有一个数字 Ki (0 ≤ Ki ≤ N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如: 3, 3, 1, 2, 5 代表了 Ki(K1=3, K2=3,……),从 1 楼开始。在 1 楼,按“上”可以到 4 楼,按“下”是不起作用的,因为没有 -2 楼。那么,从 A 楼到 B 楼至少要按几次按钮呢?
输入格式
共二行。 第一行为三个用空格隔开的正整数,表示 N, A, B(1≤N≤200,1≤A,B≤N )。 第二行为 N 个用空格隔开的非负整数,表示 Ki。
5 1 5
3 3 1 2 5
输出格式
一行,即最少按键次数,若无法到达,则输出 -1
。
3
二、思路分析:
首先看一下输入数据是什么意思,首先输入一个N, A, B,也就是分别输入楼层数(N)、开始楼层(A)、 终点楼层(B)。 在例子中,我们的 楼层数N是5,也就是说有5层楼,第二行就是这5层楼的每层楼的数字k。
1、题目中说到只有四个按钮:开,关,上,下,上下的层数等于当前楼层上的那个数字,众所周知,电梯的楼层到了的时候啊,它是会自动打开的,没有人进来的时候,也会自动关上,这里求的是最少按几个按钮,所以我们在这里不用看开关,也就是可以看作该楼层只有两个按钮 +k 、 -k
2、题目中提到最少按几次,很明显,这是一个搜索题。当出现最少的时候,我们就可以考虑用广搜了(也可以用深搜做的啦)
3、这里注意一下,就是我们在不同的按钮次数时遇到停在同一楼层,这时候就会出现一个重复的且没有必要的搜索,所以我们需要在搜索的时候加个条件。
三、AC 代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sr = new Scanner (System.in);
int N = sr.nextInt();
int A = sr.nextInt();
int B = sr.nextInt();
// 广搜必备队列
Queue<Fset> Q = new LinkedList<Fset>();
// 一个记忆判断,看看这层楼是不是来过
boolean[] visit = new boolean[N+1];
// 来存楼梯按钮的,假设第3层的k是2, 那么 k[3][0]=2 (向上的按钮)、 k[3][1]=-2 (向下的按钮)
int[][] k = new int [N+1][2];
for(int i = 1 ; i <= N ; i++){
k[i][0] = sr.nextInt();
k[i][1] = -k[i][0];
}
// 存一个起始楼层和按钮次数到队列
Q.add(new Fset(A,0));
// 当队列为空也就是所以能走的路线都走过了,没有找到就可以返回-1了
while(!Q.isEmpty()){
Fset t = Q.poll();
// 找到终点楼层,不用找了直接输出并退出搜索
if(t.floor == B){
System.out.println(t.count);
return;
}
//
for(int j = 0 ; j < 2 ; j++){
// 按键后到的楼层
int f = t.floor + k[t.floor][j];
// 判断按键后到的楼层是否有效和是否走过
if(f >= 1 && f <= N && visit[f]!=true) {
Q.add(new Fset(f,t.count+1));
// 做标记
visit[f]=true;
}
}
}
// 没找到
System.out.println(-1);
}
}
class Fset{
int floor; // 当前楼层
int count; // 当前按键次数
public Fset(int floor, int count) {
this.floor = floor;
this.count = count;
}
}
四、总结:
为什么用的队列呢? 因为队列的排队取出的,首先判断的一定是按钮次数最少的,感觉这道题用广搜或者深搜效果其实差不多,我写的深搜多一个判断,就是当当前次数超过我找到的最少按钮次数,我就丢弃这个。 广搜像晕染吧,往四周分散搜索,
嗯,就酱~