微信小程序:一起玩连线,一个算法来搞定
微信小程序:一起玩连线
游戏玩法
将相同颜色的结点连接在一起,连线之间不能交叉。
算法思想
转换为多个源点到达对应终点的路径问题,且路径之间不相交。按照dfs方式寻找两个结点路径,一条路径探索完之后,标记地图并记录路径,然后探索下一条路径,以此类推。路径探索失败之后,地图进行标记回退,路径也回退。
import com.sun.org.apache.xml.internal.serialize.LineSeparator; import java.util.*; import java.util.stream.IntStream; /** * @author hujunzheng * @create 2018-07-01 16:12 **/ public class LineTogether { private static final int[][] dir = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}}; private boolean[][] map; private List<TogetherNode> togetherNodes; public LineTogether() { Scanner scanner = new Scanner(System.in); int width = scanner.nextInt(); int height = scanner.nextInt(); int pairNodes = scanner.nextInt(); this.map = new boolean[width + 2][]; for (int i = 0; i < width + 2; ++i) { map[i] = new boolean[height + 2]; } for (int i = 1; i <= width; ++i) { for (int j = 1; j <= height; ++j) { map[i][j] = true; } } togetherNodes = new ArrayList<>(); IntStream.range(0, pairNodes).forEach(i -> { int bx = scanner.nextInt(); int by = scanner.nextInt(); map[bx][by] = false; Node begin = new Node(bx, by); int ex = scanner.nextInt(); int ey = scanner.nextInt(); map[ex][ey] = false; Node end = new Node(ex, ey); togetherNodes.add(new TogetherNode(begin, end)); }); this.printMap(); } public void resolve() { if (this.togetherNodes.size() == 0) { return; } Node begin = togetherNodes.get(0).begin; Node end = togetherNodes.get(0).end; boolean success = this.process(0, begin.x, begin.y, end.x, end.y); System.out.println(success ? "路径探测成功" : "路径探测失败"); } private void printMap() { StringBuilder result = new StringBuilder(); for (int i = 0; i < map.length; ++i) { for (int j = 0; j < map[i].length; ++j) { result.append(map[i][j] ? 1 : 0).append(" "); } result.append(LineSeparator.Windows); } System.out.println(result.toString()); } private boolean process(int ix, int bx, int by, int ex, int ey) { //如果 map[bx][by] == false, 说明是端点 boolean endpoint = !map[bx][by]; map[bx][by] = false; List<Node> path = togetherNodes.get(ix).path; path.add(new Node(bx, by)); //到达终点 if (bx == ex && by == ey) { if (ix + 1 >= togetherNodes.size()) { return true; } Node begin = togetherNodes.get(ix + 1).begin; Node end = togetherNodes.get(ix + 1).end; //下一个路径探索 boolean success = this.process(ix + 1, begin.x, begin.y, end.x, end.y); if (success) return success; } else { for (int i = 0; i < dir.length; ++i) { int nextx = bx + dir[i][0]; int nexty = by + dir[i][1]; //如果节点标记为false,并且节点不是终节点的时候 if (!map[nextx][nexty] && !(nextx == ex && nexty == ey)) { continue; } boolean success = this.process(ix, nextx, nexty, ex, ey); if (success) return true; } } if (!endpoint) { map[bx][by] = true; } path.remove(path.size() - 1); return false; } public String fetchResult() { if (togetherNodes.size() == 0) { return ""; } StringBuilder result = new StringBuilder(); togetherNodes.stream().map(TogetherNode::getPath).forEach( path -> { for (Iterator<Node> it = path.iterator(); it.hasNext(); ) { Node node = it.next(); result.append("(") .append(node.x) .append(":") .append(node.y) .append(")"); if (it.hasNext()) { result.append("->"); } } result.append(LineSeparator.Windows); } ); return result.toString(); } private class Node { public int x; public int y; public Node(int x, int y) { this.x = x; this.y = y; } } private class TogetherNode { public Node begin; public Node end; private List<Node> path; public TogetherNode(Node begin, Node end) { this.begin = begin; this.end = end; path = new ArrayList<>(); } public List<Node> getPath() { return path; } } public static void main(String[] args) { LineTogether lt = new LineTogether(); lt.resolve(); System.out.println(lt.fetchResult()); } }
输入数据
5 5 5 3 1 1 4 4 1 4 5 4 2 2 3 4 4 5 5 1 5 2 4
输出数据
路径探测成功 (3:1)->(2:1)->(1:1)->(1:2)->(1:3)->(1:4) (4:1)->(5:1)->(5:2)->(5:3)->(4:3)->(3:3)->(3:4)->(3:5)->(4:5) (4:2)->(3:2)->(2:2)->(2:3) (4:4)->(5:4)->(5:5) (1:5)->(2:5)->(2:4)
操作效果