题目描述:
你正在参与祖玛游戏的一个变种。
在这个祖玛游戏变体中,桌面上有 一排 彩球,每个球的颜色可能是:红色 'R'、黄色 'Y'、蓝色 'B'、绿色 'G' 或白色 'W' 。你的手中也有一些彩球。
你的目标是 清空 桌面上所有的球。每一回合:
从你手上的彩球中选出 任意一颗 ,然后将其插入桌面上那一排球中:两球之间或这一排球的任一端。
接着,如果有出现 三个或者三个以上 且 颜色相同 的球相连的话,就把它们移除掉。
如果这种移除操作同样导致出现三个或者三个以上且颜色相同的球相连,则可以继续移除这些球,直到不再满足移除条件。
如果桌面上所有球都被移除,则认为你赢得本场游戏。
重复这个过程,直到你赢了游戏或者手中没有更多的球。
给你一个字符串 board ,表示桌面上最开始的那排球。另给你一个字符串 hand ,表示手里的彩球。请你按上述操作步骤移除掉桌上所有球,计算并返回所需的 最少 球数。如果不能移除桌上所有的球,返回 -1 。
方法一(记忆化搜索+回溯):
class Solution {
public:
int inf = 6;
//记录搜索过的状态,对应的数字为该状态的最小操作数
unordered_map<string, int> state;
//从j开始向左右扩散,消除都是newboard[j]的字符
string remove(string& newboard, int j)
{
if (newboard.size() == 0)
{
return newboard;
}
int left = j;
int right = j;
while (left - 1 >= 0 && newboard[left - 1] == newboard[left])
{
left--;
}
while (right + 1 <= newboard.size() && newboard[right + 1] == newboard[right])
{
right++;
}
//count是相同的字符的个数,大于等于3则删除
int count = right - left + 1;
if (count >= 3)
{
newboard.erase(left, count);
//递归,用来解决链锁反应
return remove(newboard, left);
}
return newboard;
}
int dfs(string& curboard, vector<char>& curhand)
{
//如果已经消除完了,就返回0
if (curboard.size() == 0)
{
return 0;
}
//记忆化搜索,出现相同的状态就返回
if (state.count(curboard))
{
return state[curboard];
}
int ans = inf;
//将手中的球插入不同的位置中
for (int i = 0; i < curhand.size(); i++)
{
char ch = curhand[i];
//如果ch == '0',说明这个球已经用过了
if (ch != '0')
{
for (int j = 0; j < curboard.size(); j++)
{
string newboard;
newboard += curboard.substr(0, j);
newboard.push_back(ch);
newboard += curboard.substr(j);
//进行删除操作
newboard = remove(newboard, j);
//在进入下一层递归之前,将curhand[i]设为'0',表示这个球已经用过了
curhand[i] = '0';
ans = min(ans, dfs(newboard, curhand) + 1);
//回溯,恢复状态
curhand[i] = ch;
}
}
}
//记录当前状态已经被搜索过了
state[curboard] = ans;
return ans;
}
int findMinStep(string board, string hand) {
vector<char> curhand(hand.size());
//不知道为什么,vector<char>不能够使用push_back()函数,只能用赋值了
for (int i = 0; i < curhand.size(); i++)
{
curhand[i] = hand[i];
}
int ans = dfs(board, curhand);
return ans == inf ? -1 : ans;
}
};
今天这道题真是写到要吐了,看着题解都写了半天,写完之后又debug了半天。
看到最小操作数的字眼,本想用bfs,但这题的board和hand是随时变化的,所以没能写出来,还是用了最简单的dfs来做。
这道题还是颇有收获的,加强学习了一下字符串的截取、删除、添加操作,还有第一次在dfs中使用。