from the start by passing all the checkpoints.
import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Scanner; class node { int x, y; int index; int step; }; /** * 状态压缩DP,总共的状态数量为2^(checkPointsNum+1)个 * * @created Oct 29, 2014 * @author chenshanfu */ public class Orienteering_ori { private static int height, width; private static int[][] shortestDistance;// checkPoints之间的最短距离 private static int[][] f;// f[k][state] 到达第k个点的所经过的状态为state的 private static int checkPointsNum; private static int stateNum; private static boolean[][] isvisited;//记录isvisited[i][j]是否已经遍历过 // 增加一层映射关系,@坐标-->index 映射 private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(); private static node startPoint = new node(); private static node endPoint = new node(); private static char[][] a;// 原始地图 private static int[][] dir = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };//可以遍历的4个方向 private static boolean isException;//输入的参数异常 private static int startPointsNum = 0; private static int endPointsNum = 0; /** * 读取数据,同时进行参数初始化 * * @created Oct 29, 2014 * @author chenshanfu */ @SuppressWarnings("resource") public static void init() { Scanner input = new Scanner(System.in); String line = ""; line = input.nextLine().trim(); if (line.split(" ").length != 2) { isException = true; } else { width = Integer.parseInt(line.split(" ")[0]); height = Integer.parseInt(line.split(" ")[1]); if (width < 1 || width > 100 || height < 1 || width > 100) { isException = true; } a = new char[height][width]; int checkPointsIndex = 0; for (int i = 0; i < height; i++) { line = input.nextLine().trim(); if (width != line.length()) { isException = true; break; } for (int j = 0; j < width; j++) { char c = line.charAt(j); a[i][j] = c; int tmp = i * width + j; if (c == '@') { map.put(tmp, ++checkPointsIndex); } else if (c == 'S') { startPoint.x = i; startPoint.y = j; startPoint.step = 0; startPoint.index = tmp; startPointsNum++; } else if (c == 'G') { endPoint.x = i; endPoint.y = j; endPoint.step = 0; endPoint.index = tmp; endPointsNum++; } } } checkPointsNum = checkPointsIndex; if (startPointsNum != 1 || endPointsNum != 1 || checkPointsNum < 0 || checkPointsNum > 18) { isException = true; } stateNum = (int) Math.pow(2.0, 1.0 * checkPointsNum + 1); map.put(startPoint.index, 0); map.put(endPoint.index, checkPointsNum + 1); /* * System.out.println("stateNum:"+stateNum); * System.out.println("checkPointsNum:"+checkPointsNum); for(Integer * s:map.keySet()){ System.out.println("**"+s+":"+map.get(s)); } */ f = new int[checkPointsNum + 2][stateNum]; isvisited = new boolean[height][width]; shortestDistance = new int[checkPointsNum + 2][checkPointsNum + 2];// shortestDistance // 初始 for (int i = 0; i < checkPointsNum + 2; i++) { for (int j = i + 1; j < checkPointsNum + 2; j++) { shortestDistance[i][j] = Integer.MAX_VALUE; shortestDistance[j][i] = Integer.MAX_VALUE; } } } } /** * * 计算初始节点s到其他checkPoints之间的最短距离,利用BFS实现 * @param s * @created Oct 29, 2014 * @author chenshanfu */ public static void bfs(node s) { LinkedList<node> queue = new LinkedList<node>(); queue.add(s); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { isvisited[i][j] = false; } } isvisited[s.x][s.y] = true; while (!queue.isEmpty()) { node front = new node(); front = queue.getFirst(); queue.removeFirst(); for (int i = 0; i < 4; i++) { node tmpnode = new node(); tmpnode.x = front.x + dir[i][0]; tmpnode.y = front.y + dir[i][1]; if (tmpnode.x >= 0 && tmpnode.x < height && tmpnode.y >= 0 && tmpnode.y < width && !isvisited[tmpnode.x][tmpnode.y] && a[tmpnode.x][tmpnode.y] != '#') { isvisited[tmpnode.x][tmpnode.y] = true; tmpnode.step = front.step + 1; tmpnode.index = tmpnode.x * width + tmpnode.y; queue.add(tmpnode); if (map.get(tmpnode.index) != null) { shortestDistance[map.get(s.index)][map .get(tmpnode.index)] = tmpnode.step; } } } } } /** * 计算所有的checkPoints之间的最小距离 * * @created Oct 29, 2014 * @author chenshanfu */ public static void getMinDistance() { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (a[i][j] == '@' || a[i][j] == 'S' || a[i][j] == 'G') { node tmpNode = new node(); tmpNode.x = i; tmpNode.y = j; tmpNode.index = i * width + j; tmpNode.step = 0; bfs(tmpNode); } } } // 初始化@到S的最短距离 for (int i = 1; i < checkPointsNum + 2; i++) { f[i][0] = shortestDistance[i][0]; } } /** * 打印最短路径信息 * * @created Oct 29, 2014 * @author chenshanfu */ public static void print() { for (int i = 0; i < checkPointsNum + 2; i++) { for (int j = 0; j < checkPointsNum + 2; j++) { System.out.print(shortestDistance[i][j] + " "); } System.out.println(); } } /** * 状态压缩DP,求解到第k个点并且经过state状态的最优解,同时记录中间递归结果,加速搜索进度 * * @param k * @param state * @return * @created Oct 29, 2014 * @author chenshanfu */ public static int solve(int k, int state) { // System.out.println("k="+k+" state:"+state); if (f[k][state] > 0 && f[k][state] < Integer.MAX_VALUE) return f[k][state]; else { int ans = Integer.MAX_VALUE; for (int i = 1; i < checkPointsNum + 2; i++) { if ((state & (int) Math.pow(2.0, 1.0 * (i - 1))) != 0) { int subsolve = solve(i, state ^ (int) Math.pow(2.0, 1.0 * (i - 1)));//最好用(1 << (i - 1)))位运算来实现,方便快捷 if (shortestDistance[i][k] != Integer.MAX_VALUE && subsolve != Integer.MAX_VALUE) { int sub = subsolve + shortestDistance[i][k]; if (sub < ans) { ans = sub; } } } } f[k][state] = ans; return ans; } } public static void main(String[] args) { // TODO Auto-generated method stub init(); if (isException) { System.out.println("-1"); } else { getMinDistance(); // print(); if (isException || shortestDistance[0][checkPointsNum + 1] == Integer.MAX_VALUE) { System.out.println("-1"); } else { int ans = solve(checkPointsNum + 1, (int) Math.pow(2.0, 1.0 * checkPointsNum) - 1); if (ans == Integer.MAX_VALUE) System.out.println("-1"); else System.out.println(ans); } } } }
8 6 ######## #@....G# ##.##@## #[email protected]# #@.....# ######## 18 8 6 ######## #@....G# ######## #[email protected]# #@.....# ######## -1 5 4 ##### #...# #S#G# ##### 4 5 5 ##### #.@@# #S### #..G# ##### 9 5 5 ##### #S..# ##G## #..@# ##### 6 5 5 ####@ #.@@# #S### #..G# ##### -1 8 6 ######## #@.S..G# #####@## #..##... #@....@# ######## 23 8 6 ######## #@....G# #####@## #..S#... #@....@# ######## 21 8 6 ######## #S.S..G# #####@## #..##... #@....@# ######## -1 8 6 ######## #@.S..G# ######## #..##... #@....@# ######## -1 8 6 ######## #@.S..G. #######. #..##... #@....@# ######## 27 8 6 ######## #@.S..G. #.#####. #..##... #@....@# ######## 15