488.祖玛游戏

回忆一下祖玛游戏。现在桌上有一串球,颜色有红色(R),黄色(Y),蓝色(B),绿色(G),还有白色(W)。 现在你手里也有几个球。

每一次,你可以从手里的球选一个,然后把这个球插入到一串球中的某个位置上(包括最左端,最右端)。接着,如果有出现三个或者三个以上颜色相同的球相连的话,就把它们移除掉。重复这一步骤直到桌上所有的球都被移除。

找到插入并可以移除掉桌上所有球所需的最少的球数。如果不能移除桌上所有的球,输出 -1 。

示例:
输入: "WRRBBW", "RB" 
输出: -1 
解释: WRRBBW -> WRR[R]BBW -> WBBW -> WBB[B]W -> WW (翻译者标注:手上球已经用完,桌上还剩两个球无法消除,返回-1)

输入: "WWRRBBWW", "WRBRW" 
输出: 2 
解释: WWRRBBWW -> WWRR[R]BBWW -> WWBBWW -> WWBB[B]WW -> WWWW -> empty

输入:"G", "GGGGG" 
输出: 2 
解释: G -> G[G] -> GG[G] -> empty 

输入: "RBYYBBRRB", "YRBGB" 
输出: 3 
解释: RBYYBBRRB -> RBYY[Y]BBRRB -> RBBBRRB -> RRRB -> B -> B[B] -> BB[B] -> empty 

标注:

  1. 你可以假设桌上一开始的球中,不会有三个及三个以上颜色相同且连着的球。
  2. 桌上的球不会超过20个,输入的数据中代表这些球的字符串的名字是 "board" 。
  3. 你手中的球不会超过5个,输入的数据中代表这些球的字符串的名字是 "hand"。
  4. 输入的两个字符串均为非空字符串,且只包含字符 'R','Y','B','G','W'。

class Solution {
public:
    int findMinStep(string board, string hand) {
        int res = INT_MAX;
        unordered_map<char, int> m;
        for (char c : hand) ++m[c];
        res = helper(board, m);
        return res == INT_MAX ? -1 : res;
    }
    int helper(string board, unordered_map<char, int>& m) {
        board = removeConsecutive(board);
        if (board.empty()) return 0;
        int cnt = INT_MAX, j = 0;
        for (int i = 0; i <= board.size(); ++i) {
            if (i < board.size() && board[i] == board[j]) continue;
            int need = 3 - (i - j);
            if (m[board[j]] >= need) {
                m[board[j]] -= need;
                int t = helper(board.substr(0, j) + board.substr(i), m);
                if (t != INT_MAX) cnt = min(cnt, t + need);
                m[board[j]] += need;
            }
            j = i;
        }
        return cnt;
    }
    string removeConsecutive(string board) {
        for (int i = 0, j = 0; i <= board.size(); ++i) {
            if (i < board.size() && board[i] == board[j]) continue;
            if (i - j >= 3) return removeConsecutive(board.substr(0, j) + board.substr(i));
            else j = i;
        }
        return board;
    }
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是祖玛游戏的代码,使用C++实现: ```c++ #include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> using namespace std; int n, ans; // n表示小球的个数,ans表示最少需要几次操作 char s[200]; int find(int l, int r) // 找到最长的一段相同颜色的小球 { int i = l, j = r; while (i < j) { while (i < j && s[i] == s[i+1]) i++; while (i < j && s[j] == s[j-1]) j--; if (i < j && s[i] == s[j]) i++, j--; else break; } return i; } void solve() { ans = n; for (int i = 0; i < n; i++) { int j = find(i, n-1); if (j < n-1) // 如果有可以消除的小球 { int k; for (k = j+1; k < n; k++) if (s[k] != s[j]) break; // 找到第一个与s[j]颜色不同的小球 for (int l = k-j; l >= 0; l--) { // 枚举将s[j]和后面的l个小球消除 int start = max(0, i-l); // left int end = min(n-1, j+1); // right for (int r = start; r <= end; r++) { int t = find(start, end); char c = s[t]; int len = t - r + 1; for (int p = t+1; p < n; p++) s[p-len] = s[p]; // 将后面的小球向前移len个位置 n -= len; ans = min(ans, l+1 + solve()); // 递归 n += len; for (int p = n-1; p >= t+1-len; p--) s[p+len] = s[p]; // 将小球复原 for (int p = t-l+1; p <= t; p++) s[p] = c; } } break; } } } int main() { while (cin >> s && s[0] != 'E') { n = strlen(s); solve(); cout << ans << endl; } return 0; } ``` 该代码使用了分治法,对于每个区间,找到其中最长的一段相同颜色的小球,然后枚举将这一段小球和之后的小球一起消除的情况,递归求解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值