Leetcode freedom trail

本文解析了 Fallout4 游戏中 Road to Freedom 任务中 Freedom Trail Ring 的旋转问题,旨在找到拼写特定关键词所需的最小步数。采用 DP 方法,通过构建 dp 数组来记录每一步的最小步数。

题目

In the video game Fallout 4, the quest “Road to Freedom” requires players to reach a metal dial called the “Freedom Trail Ring”, and use the dial to spell a specific keyword in order to open the door.

Given a string ring, which represents the code engraved on the outer ring and another string key, which represents the keyword needs to be spelled. You need to find the minimum number of steps in order to spell all the characters in the keyword.

Initially, the first character of the ring is aligned at 12:00 direction. You need to spell all the characters in the string key one by one by rotating the ring clockwise or anticlockwise to make each character of the string key aligned at 12:00 direction and then by pressing the center button.
At the stage of rotating the ring to spell the key character key[i]:
You can rotate the ring clockwise or anticlockwise one place, which counts as 1 step. The final purpose of the rotation is to align one of the string ring’s characters at the 12:00 direction, where this character must equal to the character key[i].
If the character key[i] has been aligned at the 12:00 direction, you need to press the center button to spell, which also counts as 1 step. After the pressing, you could begin to spell the next character in the key (next stage), otherwise, you’ve finished all the spelling.

题目分析

这道题是通过扭动转盘来获取相应的字符,从而组成key。题目的要求是返回最小的步骤。

该题是寻找最小的路径步骤,因此所有的步骤都应该遍历,这里就使用DP思想。DP部分其实不是很难,和书上的edit distance是一致的,找到两个字符串之间的distance。

对于我而言,难点在于旋转时的下标获取….一开始想到使用edit distance 的方法来解决这道题,自然就会想到构建一个[key.length() + 1][ring.length() + 1]大小的dp数组来记录步骤数,但在这里,那个旋转后的下标获取就有点问题了,因此最终换成[key.length()][ring.length()]大小的dp数组。

解题步骤:
1. 首先建立dp[key.length][ring.lenth]的数组,初始化为最大值0X7FFFFFFF。dp(i,j)表示第i个key,当前位置为j的最小step。
2. 从左到右,从上往下依次寻找最短的路径。如果key[i]和ring[j]不相等,则直接跳过。否则,从j位置开始,同时向左、右两边进行寻找,找到i-1步存在的路径,寻找路径的最小值。
3. 寻找完路径后,需要+1,这一步是press button
3. 最终结果返回,max(dp[key.length()1][j])0j<ring.length

源代码

class Solution {
public:
    int findRotateSteps(string ring, string key) {
        vector<vector<int> > dp(key.size(), vector<int>(ring.size(), 0x7ffffff));

        int ans = 0x0fffffff;
        //compute
        //dp(i, j) 表示完成第i个key,前一跳是i
        for (int i = 0; i < key.size(); i++) {
            for (int j = 0; j < ring.size(); j++) {
                if (key[i] == ring[j]) {
                    if (i > 0) {
                        for (int k = 0; k <= ring.size() / 2; k++) {
                            int cw = (j + k) % ring.size();
                            int ac = (j - k + ring.size()) % ring.size();
                            int walk = 0x7fffffff;
                            if (dp[i - 1][cw] != 0x7ffffff || dp[i - 1][ac] != 0x7ffffff)
                                walk = min(dp[i - 1][cw], dp[i - 1][ac]);
                            else 
                                walk = dp[i][j];
                            //rotate ring
                            dp[i][j] = min(dp[i][j], walk + k);

                        }
                    } else {
                        dp[i][j] = min(j, int(ring.length()) - j);
                    }
                    //press button
                    dp[i][j]++;
                }
                //cout << dp[i][j] << " ";
            }
            //cout << endl;
        }
        for (int i = 0; i < ring.size(); i++) {
            ans = min(ans, dp[key.size() - 1][i]);
        }
        return ans;
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值