蓝桥杯 15决赛 B4 穿越雷区(bfs)
标题:穿越雷区
X星的坦克战车很奇怪,它必须交替地穿越正能量辐射区和负能量辐射区才能保持正常运转,否则将报废。
某坦克需要从A区到B区去(A,B区本身是安全区,没有正能量或负能量特征),怎样走才能路径最短?
已知的地图是一个方阵,上面用字母标出了A,B区,其它区都标了正号或负号分别表示正负能量辐射区。
例如:
坦克车只能水平或垂直方向上移动到相邻的区。
数据格式要求:
输入第一行是一个整数n,表示方阵的大小, 4<=n<100
接下来是n行,每行有n个数据,可能是A,B,+,-中的某一个,中间用空格分开。
A,B都只出现一次。
要求输出一个整数,表示坦克从A区到B区的最少移动步数。
如果没有方案,则输出-1
例如:
用户输入:
5
则程序应该输出:
10
资源约定:
峰值内存消耗(含虚拟机) < 512M
CPU消耗 < 2000ms
==============================
思路:
最短路径=>bfs
心得:
/**调试:输出光标从输入右边开始写出,不是在输入的下一行开始->少读了一行
下面是我最初的init()方法源码:
private static void init() {
Scanner sc = new Scanner(System.in);
n =sc.nextInt(); =>这里使用的nextInt()=>使得光标 还停在这一行,nextLine就不会这样(直接读到下一行)
String s ="";
for(int i =0 ;i <n ;i ++) s +=sc.nextLine().replace(" ", "");
sc.close();
c =s.toCharArray();
isDone =new boolean[n *n];
for(int i =0 ;i <c.length ;i ++) if(c[i] =='A') a =i; else if(c[i] =='B') b =i;
总结一波:注意输入的读取光标位置,特别是同时使用nextInt和nextLine的时候
}*/
package cn.蓝桥.决赛15.B;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/*
@author weng
@build 2020年7月21日 下午7:15:30
TODO
*/
public class bfs_穿越雷区_4 {
static int n ,a ,b ;
static char[] c;
static boolean[] isDone;
static Queue<Integer> q =new LinkedList<Integer>();
static Queue<Integer> tmp =new LinkedList<Integer>();
static int ans;
public static void main(String[] args) {
init();
//读入 数据头
q.add(a);
isDone[a] =true;
int[] oper = {-1 ,n ,1};
int cur =0 ,next =0;
while(true) { //循环倒腾两个队列->bfs,每倒腾一轮 步数(ans)+1
cur =q.poll();
//遍历 操作数组
for(int o :oper) {
next =cur +o;
//过滤
if(next >=c.length) continue; //数组边界判断
else if(cur %n ==0 &&o ==-1) continue; //数据边界判断
else if((cur +1) %n ==0 &&o ==1) continue;
else if(isDone[next]) continue; //后面两条涉及数组边界问题,放在边界判断后面
else if(c[cur] ==c[next]) continue;
if(next ==b) {System.out.println(ans +1); return ;}
tmp.add(next);
isDone[next] =true;
}
if(q.size() ==0) {
if(tmp.size() ==0) {System.out.println(-1); return ;}
while(tmp.size() !=0) q.add(tmp.poll());
ans ++;
}
}
}
private static void init() {
Scanner sc = new Scanner(System.in);
n =Integer.parseInt(sc.nextLine());
String s ="";
for(int i =0 ;i <n ;i ++) s +=sc.nextLine().replace(" ", "");
sc.close();
c =s.toCharArray();
isDone =new boolean[n *n];
//n值不过100,其乘积不过10000,数组可接纳且读取不慢
for(int i =0 ;i <c.length ;i ++) if(c[i] =='A') a =i; else if(c[i] =='B') b =i;
}
}