(1)题目:
思路:
代码:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
/*
测试数据1
3 4
S**.
....
***T
测试数据2
5 6
....S*
.***..
.*..*.
*.***.
.T....
* */
static char[][] g;
static int n;//行
static int m;//列
static int[][] v;//访问数组,避免重复访问
static ArrayList<Character> ans = new ArrayList<Character>();//存放路径
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
g = new char[n][];
v = new int[n][m];
for(int i=0;i<n;i++) {
g[i] = sc.next().toCharArray();
}
//先找到起点
int x=0,y=0;
boolean flag=false;
for(int i=0;i<n&&!flag;i++) {
for(int j=0;j<m&&!flag;j++) {
if(g[i][j]=='S') {
x=i;
y=j;
flag=true;
break;
}
}
}
v[x][y]=1;//已访问
dfs(x,y);//从第一个位置开始遍历
}
private static void dfs(int x, int y) {
v[x][y]=1;//标记已访问
if(g[x][y]=='T') {//走到终点,退出
System.out.println(ans);
System.exit(0);
}
//下一个位置合法,并且是.或T,且未被访问。则将该操作加入路径集合ans
if(x+1>=0 && x+1<n && (g[x+1][y]=='.' || g[x+1][y]=='T') && v[x+1][y]!=1) {
ans.add('D');//上
int index = ans.size()-1;
dfs(x+1,y);
ans.remove(index);//回溯
}
if(x-1>=0 && x-1<n && (g[x-1][y]=='.' || g[x-1][y]=='T') && v[x-1][y]!=1) {
ans.add('U');//上
int index = ans.size()-1;
dfs(x-1,y);
ans.remove(index);//回溯
}
if(y+1>=0 && y+1<m && (g[x][y+1]=='.' || g[x][y+1]=='T') && v[x][y+1]!=1) {
ans.add('R');//上
int index = ans.size()-1;
dfs(x,y+1);
ans.remove(index);//回溯
}
if(y-1>=0 && y-1<m && (g[x][y-1]=='.' || g[x][y-1]=='T') && v[x][y-1]!=1) {
ans.add('L');//上
int index = ans.size()-1;
dfs(x,y-1);
ans.remove(index);//回溯
}
v[x][y]=0;//没有找到出口,回溯
}
}
(2)题目:最优剪枝问题
针对问题1,找出从起点S到终点T的最少步数
代码:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
/*
* 最优性剪枝(每次遍历将 多于 当前最优解步数的 直接剪掉)
* 问题:找出起点S到终点T的最少步数
测试数据1
3 4
S**.
....
***T
测试数据2
5 6
....S*
.***..
.*..*.
*.***.
.T....
* */
static char[][] g;
static int n;//行
static int m;//列
static int[][] v;//访问数组,避免重复访问
static int[][] arr = {{-1,0},{1,0},{0,1},{0,-1}};//方向的变化数组
static int ans=9999999;//记录当前最少步数
public static void main(String[] args){
//1.输出相关值
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
g = new char[n][];
v = new int[n][m];
for(int i=0;i<n;i++) {
g[i] = sc.next().toCharArray();
}
//2.先找到起点
int x=0,y=0;
boolean flag=false;
for(int i=0;i<n&&!flag;i++) {
for(int j=0;j<m&&!flag;j++) {
if(g[i][j]=='S') {
x=i;
y=j;
flag=true;
break;
}
}
}//for
//3.深度优先遍历
dfs(x,y,0);//当前起点(x,y) ,当前已走步数0
System.out.println(ans);
}
//深度优先遍历
private static void dfs(int x, int y, int step) {
//1.最优剪枝。当前已走的步数>当前最优解步数
if(step>=ans) return;
//2.已到达终点,记录最优解
if(g[x][y]=='T') {
ans = step;//在2中已把步数大于ans的剪枝
return;
}
//3.设置当前位置为已访问(完成前面2步操作后,再设置访问标志)
v[x][y]=1;
//4.针对四个方向,进行深度优先遍历
for(int i=0;i<4;i++) {
int newx = x+arr[i][0];
int newy = y+arr[i][1];
//该位置合法,并且未被访问
if(newx>=0 && newx<n && newy>=0 && newy<m && g[newx][newy]!='*' &&v[newx][newy]!=1 ) {
dfs(newx,newy,step+1);
}
}
//5.没有找到最优解,回溯
v[x][y] = 0;
}
}
(3)题目:找出起点s到终点e的所有方案数
代码:
import java.util.Scanner;
public class Main {
/*
* 思路:
测试数据
5 5
s####
.####
.####
.####
....e
正常输出:2
* */
static int n;//行
static int m;//列
static int cnt=0;//记录总的方案数
static boolean[][] v;
static int[][] t = {{1,0},{-1,0},{0,1},{0,-1}};
public static void main(String[] args){
//1.输出相关值
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();//n行
int m = sc.nextInt();//m列
char[][] g = new char[n][];
v = new boolean[n][m];
for(int i=0;i<n;i++) {
g[i] = sc.next().toCharArray();
}//for
//2.寻找起点
int x=0,y=0;
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
if(g[i][j]=='s') {
x=i;
y=j;
break;
}
}
}
//3.深度优先遍历
dfs(x,y,g);//从起点开始进行遍历
//4.输出答案
System.out.println(cnt);
}
private static void dfs(int x, int y, char[][] g) {
if(x<0 || x>=g.length || y<0 || y>=g[0].length || g[x][y]=='#' || v[x][y]) {//下标越界 或 墙壁 或已访问
return;
}
if(g[x][y]=='e') {//到达终点,方案数+1
cnt++;
return;
}
v[x][y]=true;
for(int i=0;i<4;i++) {//访问下一个位置
int xx = x+t[i][0];
int yy = y+t[i][1];
dfs(xx,yy,g);
}//for
v[x][y]=false;//回溯
}
}