ACM ZOJ 1649 (Rescue)

来源:互联网 发布:数据库测试用例 编辑:程序博客网 时间:2024/06/05 23:04

题目链接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1649

思路一 广度优先搜索,用优先队列实现,从a开始,当遇到r时就停止搜索

思路二 转换成最短路问题,先用一个矩阵存储matrix输入的字符,然后遍历矩阵,找到两个相邻的点:如果两个点中有#,则距离为INF;如果有且仅有1个x,则距离为1.5;如果有两个x,则距离为2;其它情况,距离为1。建立一个超级终点,求a到超级终点的距离。

程序一 宽度优先搜索

import java.util.PriorityQueue;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = Integer.parseInt(scn.next());Search search = new Search(height, width);for (int i = 0; i < height; ++i) {String str = scn.next();search.setMatrixLine(i, str.toCharArray());int position = str.indexOf("a");if (-1 != position) {search.setStartX(i);search.setStartY(position);}}search.beginSearch();}scn.close();}}class Search {private final int[][] direction = { { -1, 0 }, { 1, 0 }, { 0, -1 },{ 0, 1 } };private int height;private int width;private char[][] matrix;private int startX;private int startY;public Search(int height, int width) {this.height = height;this.width = width;matrix = new char[height][width];}public void beginSearch() {Queue<Node> queue = new PriorityQueue<Node>();queue.offer(new Node(startX, startY, 0));matrix[startX][startY] = '#';while (!queue.isEmpty()) {Node node = queue.poll();for (int k = 0; k < 4; ++k) {int nextX = node.getX() + direction[k][0];int nextY = node.getY() + direction[k][1];int nextTime = node.getTime() + 1;Node tmp = new Node(nextX, nextY, nextTime);if (0 > nextX || nextX >= height || 0 > nextY || nextY >= width|| '#' == matrix[nextX][nextY]) {continue;}if ('r' == matrix[nextX][nextY]) {System.out.println(nextTime);return;} else if ('x' == matrix[nextX][nextY]) {tmp.setTime(nextTime + 1);}queue.offer(tmp);matrix[nextX][nextY] = '#';}}System.out.println("Poor ANGEL has to stay in the prison all his life.");}public void setMatrixLine(int line, char[] ch) {matrix[line] = ch;}public void setStartX(int startX) {this.startX = startX;}public void setStartY(int startY) {this.startY = startY;}}class Node implements Comparable<Node> {private int x;private int y;private int time;public Node(int x, int y, int time) {this.x = x;this.y = y;this.time = time;}public int getX() {return x;}public int getY() {return y;}public int getTime() {return time;}public void setTime(int time) {this.time = time;}@Overridepublic int compareTo(Node node) {if (this.time != node.time) {return this.time - node.time;} else if (this.x != node.x) {return this.x - node.x;} else {return this.y - node.y;}}}

程序二 dijkstra 优先队列优化算法

import java.util.Arrays;import java.util.PriorityQueue;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = Integer.parseInt(scn.next());int pointsNumber = height * width + 2;int edgesNumber = 5 * width * height - 2 * (height + width);char[][] matrix = new char[height][width];for (int i = 0; i < height; i++) {matrix[i] = scn.next().toCharArray();}Dijkstra dijkstra = new Dijkstra(pointsNumber, edgesNumber);int initStart = -1;int initEnd = height * width + 1;for (int i = 0; i < height - 1; ++i) {for (int j = 0; j < width - 1; ++j) {int start = i * width + j + 1;int end = i * width + j + 1 + 1;if ('#' != matrix[i][j] && '#' != matrix[i][j + 1]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i][j + 1]) {distance += 0.5;}dijkstra.addEdge(start, end, distance);dijkstra.addEdge(end, start, distance);}end = (i + 1) * width + j + 1;if ('#' != matrix[i][j] && '#' != matrix[i + 1][j]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i + 1][j]) {distance += 0.5;}dijkstra.addEdge(start, end, distance);dijkstra.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {dijkstra.addEdge(i * width + j + 1, initEnd, 0);}}}for (int i = height - 1, j = 0; j < width - 1; ++j) {int start = i * width + j + 1;int end = i * width + j + 1 + 1;if ('#' != matrix[i][j] && '#' != matrix[i][j + 1]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i][j + 1]) {distance += 0.5;}dijkstra.addEdge(start, end, distance);dijkstra.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {dijkstra.addEdge(i * width + j + 1, initEnd, 0);}}for (int j = width - 1, i = 0; i < height - 1; ++i) {int start = i * width + j + 1;int end = (i + 1) * width + j + 1;if ('#' != matrix[i][j] && '#' != matrix[i + 1][j]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i + 1][j]) {distance += 0.5;}dijkstra.addEdge(start, end, distance);dijkstra.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {dijkstra.addEdge(i * width + j + 1, initEnd, 0);}}if ('a' == matrix[height - 1][width - 1]) {initStart = height * width;}if ('r' == matrix[height - 1][width - 1]) {dijkstra.addEdge(height * width, initEnd, 0);}double distance = dijkstra.calculateDistance(initStart, initEnd);if (dijkstra.hasMinDistance()) {System.out.println(String.format("%.0f", distance));} else {System.out.println("Poor ANGEL has to stay in the prison all his life.");}}scn.close();}}class Dijkstra {private final double INF = Double.MAX_VALUE / 2;private int pointsNumber;private int edgesNumber;private double[] edgesDistance;private int[] edgesEnd;private int[] nextStart;private int[] startMax;private boolean[] visit;private double[] resultDistance;private int[] prePoint;private double resultMinDistance;public Dijkstra(int pointsNumber, int edgesNumber) {this.pointsNumber = pointsNumber;this.edgesNumber = 0;edgesDistance = new double[edgesNumber];edgesEnd = new int[edgesNumber];nextStart = new int[edgesNumber];startMax = new int[pointsNumber];Arrays.fill(startMax, -1);visit = new boolean[pointsNumber];resultDistance = new double[pointsNumber];prePoint = new int[pointsNumber];resultMinDistance = INF;}public void addEdge(int start, int end, double distance) {edgesDistance[edgesNumber] = distance;edgesEnd[edgesNumber] = end;nextStart[edgesNumber] = startMax[start];startMax[start] = edgesNumber++;}public double calculateDistance(int initStart, int initEnd) {Arrays.fill(visit, false);Arrays.fill(resultDistance, INF);Arrays.fill(prePoint, -1);visit[initStart] = true;resultDistance[initStart] = 0;int currentPoint = initStart;Queue<Node> queue = new PriorityQueue<Node>();for (int i = 1; i < pointsNumber; ++i) {for (int j = startMax[currentPoint]; j != -1; j = nextStart[j]) {int k = edgesEnd[j];if (!visit[k]&& resultDistance[currentPoint] < resultDistance[k]- edgesDistance[j]) {resultDistance[k] = resultDistance[currentPoint]+ edgesDistance[j];queue.offer(new Node(k, resultDistance[k]));prePoint[k] = currentPoint;}}while (!queue.isEmpty()) {Node tmp = queue.peek();if (visit[tmp.getPoint()]) {queue.poll();} else {break;}}if (queue.isEmpty()) {break;}currentPoint = queue.poll().getPoint();visit[currentPoint] = true;if (currentPoint == initEnd) {break;}}resultMinDistance = resultDistance[initEnd];return resultDistance[initEnd];}public boolean hasMinDistance() {if (INF <= resultMinDistance) {return false;} else {return true;}}}class Node implements Comparable<Node> {private int point;private double distance;public Node(int point, double distance) {this.point = point;this.distance = distance;}public int getPoint() {return point;}public double getDistance() {return distance;}@Overridepublic int compareTo(Node qnode) {if (this.distance > qnode.distance) {return 1;} else if (this.distance < qnode.distance) {return -1;} else {return this.point - qnode.point;}}}

程序三 bellman-ford 算法

import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = Integer.parseInt(scn.next());int pointsNumber = height * width + 2;int edgesNumber = 5 * width * height - 2 * (height + width);char[][] matrix = new char[height][width];for (int i = 0; i < height; i++) {matrix[i] = scn.next().toCharArray();}BellmanFord bellmanFord = new BellmanFord(pointsNumber, edgesNumber);int initStart = -1;int initEnd = height * width + 1;for (int i = 0; i < height - 1; ++i) {for (int j = 0; j < width - 1; ++j) {int start = i * width + j + 1;int end = i * width + j + 1 + 1;if ('#' != matrix[i][j] && '#' != matrix[i][j + 1]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i][j + 1]) {distance += 0.5;}bellmanFord.addEdge(start, end, distance);bellmanFord.addEdge(end, start, distance);}end = (i + 1) * width + j + 1;if ('#' != matrix[i][j] && '#' != matrix[i + 1][j]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i + 1][j]) {distance += 0.5;}bellmanFord.addEdge(start, end, distance);bellmanFord.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {bellmanFord.addEdge(i * width + j + 1, initEnd, 0);}}}for (int i = height - 1, j = 0; j < width - 1; ++j) {int start = i * width + j + 1;int end = i * width + j + 1 + 1;if ('#' != matrix[i][j] && '#' != matrix[i][j + 1]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i][j + 1]) {distance += 0.5;}bellmanFord.addEdge(start, end, distance);bellmanFord.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {bellmanFord.addEdge(i * width + j + 1, initEnd, 0);}}for (int j = width - 1, i = 0; i < height - 1; ++i) {int start = i * width + j + 1;int end = (i + 1) * width + j + 1;if ('#' != matrix[i][j] && '#' != matrix[i + 1][j]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i + 1][j]) {distance += 0.5;}bellmanFord.addEdge(start, end, distance);bellmanFord.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {bellmanFord.addEdge(i * width + j + 1, initEnd, 0);}}if ('a' == matrix[height - 1][width - 1]) {initStart = height * width;}if ('r' == matrix[height - 1][width - 1]) {bellmanFord.addEdge(height * width, initEnd, 0);}double distance = bellmanFord.calculateDistance(initStart, initEnd);if (bellmanFord.hasMinDistance()) {System.out.println(String.format("%.0f", distance));} else {System.out.println("Poor ANGEL has to stay in the prison all his life.");}}scn.close();}}class BellmanFord {private final double INF = Double.MAX_VALUE / 2;private int pointsNumber;private int edgesNumber;private Edge[] edge;private double[] resultDistance;private int[] prePoint;private double resultMinDistance;private boolean relax(int start, int end, double distance) {if (resultDistance[end] - distance > resultDistance[start]) {resultDistance[end] = resultDistance[start] + distance;prePoint[end] = start;return true;} else {return false;}}public BellmanFord(int pointsNumber, int edgesNumber) {this.pointsNumber = pointsNumber;this.edgesNumber = 0;edge = new Edge[edgesNumber];resultDistance = new double[pointsNumber];prePoint = new int[pointsNumber];resultMinDistance = INF;}public void addEdge(int start, int end, double distance) {edge[edgesNumber++] = new Edge(start, end, distance);}public double calculateDistance(int initStart, int initEnd) {Arrays.fill(resultDistance, INF);Arrays.fill(prePoint, -1);resultDistance[initStart] = 0;for (int i = 1; i < pointsNumber; ++i) {Boolean flag = false;for (int j = 0; j < edgesNumber; ++j) {if (relax(edge[j].getStart(), edge[j].getEnd(),edge[j].getDistance())) {flag = true;}}if (!flag) {break;}}for (int i = 0; i < edgesNumber; ++i) {if (relax(edge[i].getStart(), edge[i].getEnd(),edge[i].getDistance())) {resultMinDistance = -INF;return -INF;}}resultMinDistance = resultDistance[initEnd];return resultDistance[initEnd];}public boolean hasMinDistance() {if (hasNegativeRing() || INF <= resultMinDistance) {return false;} else {return true;}}public boolean hasNegativeRing() {if (-INF >= resultMinDistance) {return true;} else {return false;}}}class Edge {private int start;private int end;private double distance;public Edge(int start, int end, double distance) {this.start = start;this.end = end;this.distance = distance;}public int getStart() {return start;}public int getEnd() {return end;}public double getDistance() {return distance;}}

程序四 spfa 算法

import java.util.Arrays;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int height = Integer.parseInt(scn.next());int width = Integer.parseInt(scn.next());int pointsNumber = height * width + 2;int edgesNumber = 5 * width * height - 2 * (height + width);char[][] matrix = new char[height][width];for (int i = 0; i < height; i++) {matrix[i] = scn.next().toCharArray();}Spfa spfa = new Spfa(pointsNumber, edgesNumber);int initStart = -1;int initEnd = height * width + 1;for (int i = 0; i < height - 1; ++i) {for (int j = 0; j < width - 1; ++j) {int start = i * width + j + 1;int end = i * width + j + 1 + 1;if ('#' != matrix[i][j] && '#' != matrix[i][j + 1]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i][j + 1]) {distance += 0.5;}spfa.addEdge(start, end, distance);spfa.addEdge(end, start, distance);}end = (i + 1) * width + j + 1;if ('#' != matrix[i][j] && '#' != matrix[i + 1][j]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i + 1][j]) {distance += 0.5;}spfa.addEdge(start, end, distance);spfa.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {spfa.addEdge(i * width + j + 1, initEnd, 0);}}}for (int i = height - 1, j = 0; j < width - 1; ++j) {int start = i * width + j + 1;int end = i * width + j + 1 + 1;if ('#' != matrix[i][j] && '#' != matrix[i][j + 1]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i][j + 1]) {distance += 0.5;}spfa.addEdge(start, end, distance);spfa.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {spfa.addEdge(i * width + j + 1, initEnd, 0);}}for (int j = width - 1, i = 0; i < height - 1; ++i) {int start = i * width + j + 1;int end = (i + 1) * width + j + 1;if ('#' != matrix[i][j] && '#' != matrix[i + 1][j]) {double distance = 1;if ('x' == matrix[i][j]) {distance += 0.5;}if ('x' == matrix[i + 1][j]) {distance += 0.5;}spfa.addEdge(start, end, distance);spfa.addEdge(end, start, distance);}if ('a' == matrix[i][j]) {initStart = i * width + j + 1;}if ('r' == matrix[i][j]) {spfa.addEdge(i * width + j + 1, initEnd, 0);}}if ('a' == matrix[height - 1][width - 1]) {initStart = height * width;}if ('r' == matrix[height - 1][width - 1]) {spfa.addEdge(height * width, initEnd, 0);}double distance = spfa.calculateDistance(initStart, initEnd);if (spfa.hasMinDistance()) {System.out.println(String.format("%.0f", distance));} else {System.out.println("Poor ANGEL has to stay in the prison all his life.");}}scn.close();}}class Spfa {private final double INF = Double.MAX_VALUE / 2;private int pointsNumber;private int edgesNumber;private double[] edgesDistance;private int[] edgesEnd;private int[] nextStart;private int[] startMax;private boolean[] visit;private double[] resultDistance;private int[] prePoint;private int[] count;private double resultMinDistance;private boolean relax(int start, int end, double distance) {if (resultDistance[end] - distance > resultDistance[start]) {resultDistance[end] = resultDistance[start] + distance;prePoint[end] = start;return true;} else {return false;}}public Spfa(int pointsNumber, int edgesNumber) {this.pointsNumber = pointsNumber;this.edgesNumber = 0;edgesDistance = new double[edgesNumber];edgesEnd = new int[edgesNumber];nextStart = new int[edgesNumber];startMax = new int[pointsNumber];Arrays.fill(startMax, -1);visit = new boolean[pointsNumber];resultDistance = new double[pointsNumber];prePoint = new int[pointsNumber];count = new int[pointsNumber];resultMinDistance = INF;}public void addEdge(int start, int end, double distance) {edgesDistance[edgesNumber] = distance;edgesEnd[edgesNumber] = end;nextStart[edgesNumber] = startMax[start];startMax[start] = edgesNumber++;}public double calculateDistance(int initStart, int initEnd) {Arrays.fill(visit, false);Arrays.fill(resultDistance, INF);Arrays.fill(prePoint, -1);Arrays.fill(count, 0);visit[initStart] = true;resultDistance[initStart] = 0;++count[initStart];Queue<Integer> queue = new LinkedList<Integer>();queue.offer(initStart);while (!queue.isEmpty()) {int start = queue.poll();visit[start] = false;for (int i = startMax[start]; i != -1; i = nextStart[i]) {int end = edgesEnd[i];if (relax(start, end, edgesDistance[i]) && !visit[end]) {queue.offer(end);visit[end] = true;if ((++count[end]) > pointsNumber) {resultMinDistance = -INF;return -INF;}}}}resultMinDistance = resultDistance[initEnd];return resultDistance[initEnd];}public boolean hasMinDistance() {if (hasNegativeRing() || INF <= resultMinDistance) {return false;} else {return true;}}public boolean hasNegativeRing() {if (-INF >= resultMinDistance) {return true;} else {return false;}}}

 

0 0
原创粉丝点击