FINISH
翻译:
.XX.1.
..X.2.
2...X.
...XX.
XXXXX.
这样一个迷宫,起点是00 终点是右下角,1,2等数字是怪物。走一步需要1s,杀怪物如果显示的是1需要1秒,如果2需要2秒,以此类推。
思路:
BFS+优先队列剪枝 这里先不剪枝 分别用DFS BFS两个暴力法做 以后再写优先队列剪枝的情况
DFS就是深度优先搜索,把一个方向的所有可能都找完了再找另一个方向。十分简单粗暴。
BFS就是广度优先搜索,所有的点同时前进。这里要注意杀怪时间即可,如果怪物时间没跑完,你是不能继续走的。
DFS代码
void back(int time, int row, int col) {//origin time = 0//row 行 // col 列 int killTime = 1; if (!a[row][col].equals(".")) { killTime += Integer.valueOf(a[row][col]); } if (col == width - 1 && row == height - 1) { min = Math.min(min, killTime + time); return; } for (int i = 0; i < 4; i++) { switch (i) { case 0: int aim = row + 1; if (isAccessable(aim, col)) { isAccessed[aim][col] = true; back(time + killTime, aim, col); isAccessed[aim][col] = false; } break; case 1: int aim2 = row - 1; if (isAccessable(aim2, col)) { isAccessed[aim2][col] = true; back(time + killTime, aim2, col); isAccessed[aim2][col] = false; } break; case 2: int aim3 = col + 1; if (isAccessable(row, aim3)) { isAccessed[row][aim3] = true; back(time + killTime, row, aim3); isAccessed[row][aim3] = false; } break; case 3: int aim4 = col - 1; if (isAccessable(row, aim4)) { isAccessed[row][aim4] = true; back(time + killTime, row, aim4); isAccessed[row][aim4] = false; } break; } } }
BFS代码
int bfs() { int time = 0; while (true) { time++; //对当前点每个元素遍历,查看是否能生成意愿点 for (int i = 0; i < current.size(); i ++) { Point p = current.get(i); int row1 = (int) p.getX(); int col1 = (int) p.getY(); //debug 这里的横坐标 0010101010101010 why? if (row1 == height - 1 && col1 == width - 1) { return time + 1; } //如果当前点还有怪物时间,你就不能对任何点产生企图 if (flag[row1][col1] > 0) { flag[row1][col1]--; if (flag[row1][col1] == 0) { flag[row1][col1] = -1;//时间消费光了,标记数组为已走 } //产生企图,生成will集合,标记数组 } else if (flag[row1][col1] == -1) { //生成意愿 aim(row1 + 1, col1); aim(row1 - 1, col1); aim(row1, col1 + 1); aim(row1, col1 + 1); //debug 第二次取就是空的了,很有可能是之后的步骤错了 } } //debug will的size第一次是1,之后一直是0了 1,0 if (will.size() != 0) { for (int j = 0; j < will.size(); j++) { Point p1 = will.get(j); int row2 = (int) p1.getX(); int col2 = (int) p1.getY(); //如果有怪物 if (!a[row2][col2].equals(".")) { int num = Integer.valueOf(a[row2][col2]); flag[row2][col2] = num; } flag[row2][col2] = -1; current.add(p1); } will.clear(); } } }
全部代码
package ACM1000_1099; import java.awt.*; import java.util.ArrayList; import java.util.List; import java.util.Queue; public class IgnatiusAndThePrincessOne1026 { IgnatiusAndThePrincessOne1026(String[][] a) { height = a.length; width = a[0].length; this.a = new String[height][width]; isAccessed = new boolean[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { this.a[i][j] = a[i][j]; } } min = Integer.MAX_VALUE; // back(-1, 0, 0); // // System.out.print(min + ""); //0 未走 -1 已走 -2将走 正数 剩余时间//所以当前点有两种情况 -1已走,正数 有倒计时 flag = new int[height][width]; current = new ArrayList<>(); will = new ArrayList<>(); flag[0][0] = -1; Point point = new Point(0, 0); current.add(point); int result = bfs(); System.out.print(result + ""); } String[][] a; boolean[][] isAccessed; int height; int width; int min; int[][] flag; Listcurrent; List will; boolean isAccessable(int row, int col) { if (row < 0 || col < 0 || row > height - 1 || col > width - 1 || a[row][col].equals("X") || isAccessed[row][col]) { return false; } return true; } //回溯 即 dfs? void back(int time, int row, int col) {//origin time = 0//row 行 // col 列 int killTime = 1; if (!a[row][col].equals(".")) { killTime += Integer.valueOf(a[row][col]); } if (col == width - 1 && row == height - 1) { min = Math.min(min, killTime + time); return; } for (int i = 0; i < 4; i++) { switch (i) { case 0: int aim = row + 1; if (isAccessable(aim, col)) { isAccessed[aim][col] = true; back(time + killTime, aim, col); isAccessed[aim][col] = false; } break; case 1: int aim2 = row - 1; if (isAccessable(aim2, col)) { isAccessed[aim2][col] = true; back(time + killTime, aim2, col); isAccessed[aim2][col] = false; } break; case 2: int aim3 = col + 1; if (isAccessable(row, aim3)) { isAccessed[row][aim3] = true; back(time + killTime, row, aim3); isAccessed[row][aim3] = false; } break; case 3: int aim4 = col - 1; if (isAccessable(row, aim4)) { isAccessed[row][aim4] = true; back(time + killTime, row, aim4); isAccessed[row][aim4] = false; } break; } } } boolean isWillable(int row, int col) { if (row < 0 || col < 0 || row > height - 1 || col > width - 1 || a[row][col].equals("X") || isAccessed[row][col]) { return false; } if (flag[row][col] != -1 && flag[row][col] != -2) { return true; } else { return false; } } void aim(int row, int col) { //如果可产生企图 if (isWillable(row, col)) { flag[row][col] = -2; Point p = new Point(row, col); will.add(p); } } //优先队列还不是太明白 但是bfs可以试一下 int bfs() { int time = 0; while (true) { time++; //对当前点每个元素遍历,查看是否能生成意愿点 for (int i = 0; i < current.size(); i ++) { Point p = current.get(i); int row1 = (int) p.getX(); int col1 = (int) p.getY(); //debug 这里的横坐标 0010101010101010 why? if (row1 == height - 1 && col1 == width - 1) { return time + 1; } //如果当前点还有怪物时间,你就不能对任何点产生企图 if (flag[row1][col1] > 0) { flag[row1][col1]--; if (flag[row1][col1] == 0) { flag[row1][col1] = -1;//时间消费光了,标记数组为已走 } //产生企图,生成will集合,标记数组 } else if (flag[row1][col1] == -1) { //生成意愿 aim(row1 + 1, col1); aim(row1 - 1, col1); aim(row1, col1 + 1); aim(row1, col1 + 1); //debug 第二次取就是空的了,很有可能是之后的步骤错了 } } //debug will的size第一次是1,之后一直是0了 1,0 if (will.size() != 0) { for (int j = 0; j < will.size(); j++) { Point p1 = will.get(j); int row2 = (int) p1.getX(); int col2 = (int) p1.getY(); //如果有怪物 if (!a[row2][col2].equals(".")) { int num = Integer.valueOf(a[row2][col2]); flag[row2][col2] = num; } flag[row2][col2] = -1; current.add(p1); } will.clear(); } } } public static void main(final String[] args) throws Exception { String[][] a = { {".", "X", "X", ".", "1", "."}, {".", ".", "X", ".", "2", "."}, {"2", ".", ".", ".", "X", "."}, {".", ".", ".", "X", "X", "."}, {"X", "X", "X", "X", "X", "."}}; IgnatiusAndThePrincessOne1026 i = new IgnatiusAndThePrincessOne1026(a); } }
这篇文章写的真烂!但是今天状态不好。虽然这dfs bfs很快就写出来了。