1. 程式人生 > 其它 >IntelliJ IDEA 啟用碼,免費的就是香,1分鐘快速啟用IDEA!

IntelliJ IDEA 啟用碼,免費的就是香,1分鐘快速啟用IDEA!

電子遊戲“輻射4”中,任務“通向自由”要求玩家到達名為“Freedom Trail Ring”的金屬錶盤,並使用錶盤拼寫特定關鍵詞才能開門。

給定一個字串 ring,表示刻在外環上的編碼;給定另一個字串 key,表示需要拼寫的關鍵詞。您需要算出能夠拼寫關鍵詞中所有字元的最少步數。

最初,ring 的第一個字元與12:00方向對齊。您需要順時針或逆時針旋轉 ring 以使 key 的一個字元在 12:00 方向對齊,然後按下中心按鈕,以此逐個拼寫完 key 中的所有字元。

旋轉 ring 拼出 key 字元 key[i] 的階段中:

您可以將 ring 順時針或逆時針旋轉一個位置,計為1步。旋轉的最終目的是將字串 ring 的一個字元與 12:00 方向對齊,並且這個字元必須等於字元 key[i] 。
如果字元 key[i] 已經對齊到12:00方向,您需要按下中心按鈕進行拼寫,這也將算作 1 步。按完之後,您可以開始拼寫 key 的下一個字元(下一階段), 直至完成所有拼寫。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/freedom-trail
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

import java.util.*;

class Solution {

    private static int getDistance(int ringSize, int from, int to) {
        return Math.min(Math.abs(from - to), Math.min(from, to) + ringSize - Math.max(from, to));
    }


    /**
     * 簡約遞迴
     * 可見記憶化搜尋
     *
     * @param keyMap
     * @param ringSize
     * @param currentPos
     * @param index
     * @param aim
     * @return
     */
    private static int solve(Map<Character, List<Integer>> keyMap, int ringSize, int currentPos, int index, char[] aim) {
        if (index == aim.length) {
            return 0;
        }

        /**
         * 列舉所有可能
         */
        List<Integer> list = keyMap.get(aim[index]);

        int ret = Integer.MAX_VALUE;

        for (int pos : list) {
            ret = Math.min(ret, 1 + getDistance(ringSize, currentPos, pos) + solve(keyMap, ringSize, pos, index + 1, aim));
        }

        return ret;
    }

    /**
     * 簡約DP
     *
     * @param keyMap
     * @param ringSize
     * @param aim
     * @return
     */
    private static final int solve2(Map<Character, List<Integer>> keyMap, int ringSize, char[] aim) {

        int m = aim.length;
        int[][] dp = new int[m + 1][ringSize];

        for (int index = m - 1; index >= 0; --index) {
            List<Integer> list = keyMap.get(aim[index]);
            for (int currentPos = 0; currentPos < ringSize; currentPos++) {
                dp[index][currentPos] = Integer.MAX_VALUE;
                for (int pos : list) {
                    /**
                     * 不能狀態壓縮
                     * 因為currentPos依賴於下層pos,二而pos不一定在哪裡,可能比currentPos大,也可能比currentPos小
                     */
                    dp[index][currentPos] = Math.min(dp[index][currentPos], 1 + getDistance(ringSize, currentPos, pos) + dp[index + 1][pos]);
                }
            }

        }

        return dp[0][0];
    }

    public static int findRotateSteps(String ring, String key) {

        Map<Character, List<Integer>> keyMap = new HashMap<>();

        for (int i = 0; i < ring.length(); ++i) {
            List<Integer> list = keyMap.getOrDefault(ring.charAt(i), new ArrayList<>());
            list.add(i);
            keyMap.put(ring.charAt(i), list);
        }

//        return solve(keyMap, ring.length(), 0, 0, key.toCharArray());
        return solve2(keyMap, ring.length(), key.toCharArray());
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            System.out.println(findRotateSteps(in.next(), in.next()));
        }
    }
}
心之所向,素履以往 生如逆旅,一葦以航