欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JAVA程序设计:追逐游戏(LCP 21)

程序员文章站 2022-09-10 13:22:10
秋游中的小力和小扣设计了一个追逐游戏。他们选了秋日市集景区中的 N 个景点,景点编号为 1~N。此外,他们还选择了 N 条小路,满足任意两个景点之间都可以通过小路互相到达,且不存在两条连接景点相同的小路。整个游戏场景可视作一个无向连通图,记作二维数组 edges,数组中以 [a,b] 形式表示景点 a 与景点 b 之间有一条小路连通。小力和小扣只能沿景点间的小路移动。小力的目标是在最快时间内追到小扣,小扣的目标是尽可能延后被小力追到的时间。游戏开始前,两人分别站在两个不同的景点 startA 和 sta...

秋游中的小力和小扣设计了一个追逐游戏。他们选了秋日市集景区中的 N 个景点,景点编号为 1~N。此外,他们还选择了 N 条小路,满足任意两个景点之间都可以通过小路互相到达,且不存在两条连接景点相同的小路。整个游戏场景可视作一个无向连通图,记作二维数组 edges,数组中以 [a,b] 形式表示景点 a 与景点 b 之间有一条小路连通。

小力和小扣只能沿景点间的小路移动。小力的目标是在最快时间内追到小扣,小扣的目标是尽可能延后被小力追到的时间。游戏开始前,两人分别站在两个不同的景点 startA 和 startB。每一回合,小力先行动,小扣观察到小力的行动后再行动。小力和小扣在每回合可选择以下行动之一:

移动至相邻景点
留在原地
如果小力追到小扣(即两人于某一时刻出现在同一位置),则游戏结束。若小力可以追到小扣,请返回最少需要多少回合;若小力无法追到小扣,请返回 -1。

注意:小力和小扣一定会采取最优移动策略。

示例 1:

输入:edges = [[1,2],[2,3],[3,4],[4,1],[2,5],[5,6]], startA = 3, startB = 5

输出:3

解释:

JAVA程序设计:追逐游戏(LCP 21)


第一回合,小力移动至 2 号点,小扣观察到小力的行动后移动至 6 号点;
第二回合,小力移动至 5 号点,小扣无法移动,留在原地;
第三回合,小力移动至 6 号点,小力追到小扣。返回 3。

示例 2:

输入:edges = [[1,2],[2,3],[3,4],[4,1]], startA = 1, startB = 3

输出:-1

解释:

JAVA程序设计:追逐游戏(LCP 21)


小力如果不动,则小扣也不动;否则小扣移动到小力的对角线位置。这样小力无法追到小扣。

提示:

edges 的长度等于图中节点个数
3 <= edges.length <= 10^5
1 <= edges[i][0], edges[i][1] <= edges.length 且 edges[i][0] != edges[i][1]
1 <= startA, startB <= edges.length 且 startA != startB

思路:在题解中发现了一个比较好的思路,一道非常值得回味的图论好题。

JAVA程序设计:追逐游戏(LCP 21)

class Solution {

    private List<List<Integer>> e;

    public int chaseGame(int[][] edges, int startA, int startB) {

        int n = edges.length;
        int[] ingree = new int[n];
        e = new ArrayList<>();

        for (int i = 0; i < n; i++)
            e.add(new ArrayList<>());

        for (int i = 0; i < n; i++) {
            int u = edges[i][0] - 1;
            int v = edges[i][1] - 1;
            e.get(u).add(v);
            e.get(v).add(u);
            ingree[u]++;
            ingree[v]++;
        }

        int[] arr1 = new int[n];
        Arrays.fill(arr1, -1);
        --startA;
        bfs(arr1, startA);

        int[] arr2 = new int[n];
        Arrays.fill(arr2, -1);
        --startB;
        bfs(arr2, startB);

        int rest = n;
        Queue<Integer> q = new LinkedList<>();

        for (int i = 0; i < n; i++) {
            if (ingree[i] == 1)
                q.add(i);
        }

        //通过拓扑排序判断求出环的长度
        while (!q.isEmpty()) {
            int now = q.poll();
            --rest;
            for (int i = 0; i < e.get(now).size(); i++) {
                int nxt = e.get(now).get(i);
                ingree[nxt]--;
                if (ingree[nxt] == 1)
                    q.add(nxt);
            }
        }

        int ans = 1;
        if (rest == 3) {
            for (int i = 0; i < n; i++) {
                if (arr1[i] > arr2[i] + 1)
                    ans = Math.max(ans, arr1[i]);
            }
        } else {
            for (int i = 0; i < n; i++) {
                if (arr1[i] > arr2[i] + 1) {
                    if (ingree[i] > 1) {
                        ans = -1;
                        break;
                    } else
                        ans = Math.max(ans, arr1[i]);
                }
            }
        }

        return ans;

    }

    private void bfs(int[] dis, int u) {

        Queue<Integer> q = new LinkedList<>();
        q.add(u);
        dis[u] = 0;
        while (!q.isEmpty()) {
            int now = q.poll();
            for (int i = 0; i < e.get(now).size(); i++) {
                int nxt = e.get(now).get(i);
                if (dis[nxt] == -1) {
                    q.add(nxt);
                    dis[nxt] = dis[now] + 1;
                }
            }
        }

    }
}

 

本文地址:https://blog.csdn.net/haut_ykc/article/details/108585735