问题描述
给定一个R行C列的地图,地图的每一个方格可能是’#’, ‘+’, ‘-’, ‘|’, ‘.’, ‘S’, ‘T’七个字符中的一个,分别表示如下意思:
‘#’: 任何时候玩家都不能移动到此方格;
‘+’: 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非’#‘方格移动一格;
‘-’: 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非’#‘方格移动一格;
‘|’: 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非’#‘方格移动一格;
‘.’: 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为’#’,则玩家不能再移动;
‘S’: 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非’#‘方格移动一格;
‘T’: 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非’#‘方格移动一格。
此外,玩家不能移动出地图。
请找出满足下面两个性质的方格个数:
1. 玩家可以从初始位置移动到此方格;
2. 玩家不可以从此方格移动到目标位置。
输入格式
输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
接下来的R行每行都包含C个字符。它们表示地图的格子。地图上恰好有一个’S’和一个’T’。
输出格式
如果玩家在初始位置就已经不能到达终点了,就输出“I’m stuck!”(不含双引号)。否则的话,输出满足性质的方格的个数。
样例输入
5 5
–±+
…|#.
…|##
S-±T
####.
样例输出
2
样例说明
如果把满足性质的方格在地图上用’X’标记出来的话,地图如下所示:
--±+
…|#X
…|##
S-±T
####X
Java代码注释没怎么写,主要是大家应该好好研究一下广度优先搜索的算法。如果理解广搜,这个应该是比较容易理解的
import java.util.*;
public class IAmStuck {
static int a[][]= {{1,0},{-1,0},{0,1},{0,-1}};
static int n;
static int m;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
char c[][]=new char[n][m];
boolean vis[][]=new boolean[n][m];
Node start = null;
Node end = null;
sc.nextLine();
for(int i=0;i<n;i++) {//输入数据
String s=sc.nextLine();
for(int j=0;j<s.length();j++) {
c[i][j]=s.charAt(j);
if(c[i][j]=='S') {
start=new Node(i, j);
}
if(c[i][j]=='T') {
end=new Node(i, j);
}
}
}
Queue<Node> q = new LinkedList<Node>();
q.add(start);
vis[start.x][start.y]=true;
while(!q.isEmpty()) {//遍历所有从起始点开始可以访问到的点。(广度优先搜索)
Node node=q.poll();
if(c[node.x][node.y]=='+') {
for(int i=0;i<4;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&vis[t1][t2]==false) {
vis[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='-') {
for(int i=2;i<4;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&vis[t1][t2]==false) {
vis[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='|') {
for(int i=0;i<2;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&vis[t1][t2]==false) {
vis[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='.') {
for(int i=0;i<1;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&vis[t1][t2]==false) {
vis[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='T') {
for(int i=0;i<4;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&vis[t1][t2]==false) {
vis[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='S') {
for(int i=0;i<4;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&vis[t1][t2]==false) {
vis[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else {
}
}
if(vis[end.x][end.y]==false) {//如果无法访问到终点,则说明玩家在初始位置就已经不能到达终点了,就输出“I'm stuck!”(不含双引号)
System.out.println("I'm stuck!");
return ;
}
int result=0;
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {//对所有从起始点开始,都能访问到的点,判断其是否可以访问到重点
if(vis[i][j]==true&&c[i][j]!='T'&&c[i][j]!='S'&&c[i][j]!='#') {//如果不可以,则另结果+1
if(bfs(new Node(i,j),new boolean[n][m],c)==false) {
result++;
}
}
}
}
System.out.println(result);
}
static boolean bfs(Node start,boolean b[][],char c[][]){
Queue<Node> q=new LinkedList<Node>();
q.add(start);
while(!q.isEmpty()) {
Node node = q.poll();
if(c[node.x][node.y]=='+') {
for(int i=0;i<4;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&b[t1][t2]==false) {
b[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='-') {
for(int i=2;i<4;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&b[t1][t2]==false) {
b[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='|') {
for(int i=0;i<2;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&b[t1][t2]==false) {
b[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='.') {
for(int i=0;i<1;i++) {
int t1=node.x+a[i][0];
int t2=node.y+a[i][1];
if(t1>=0&&t1<n&&t2>=0&&t2<m&&c[t1][t2]!='#'&&b[t1][t2]==false) {
b[t1][t2]=true;
q.add(new Node(t1,t2));
}
}
}
else if(c[node.x][node.y]=='T') {//如果访问到终点,则返回true
return true;
}
else if(c[node.x][node.y]=='S') {//如果访问到起始点,那么一定会访问到终点
//因为如果从起始点开始没有访问到终点,那么程序已经在第101行结束了,而不会运行到此处
return true;
}
else {
}
}
//如果程序访问了所有可以访问的点而没有访问到终点,则说明无法访问到终点
return false;
}
}
class Node{
public int x;
public int y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
程序写的有点乱,希望大佬指出错误。