题意:字符串消消看,当两个或以上挨着的字符相同时才可以消去(一个单独字符无法消去),最后可以消去至空的字符串solvable,反之unsolvable。
记忆化搜索。
题解一有一处仍未理解,题解二按照题目暗示的思路进行dfs,注意理解为什么是先判断xy型,然后AxA,AxAyA。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200;
char str[maxn];
int dp[maxn][maxn];
bool dfs(int l, int r)
{
if(l > r) return 1;
if(l == r) return 0; //单独的一个字母,无法消去,把尽可能多的判断语句写在dfs函数开始,避免写在中间出错
if(dp[l][r] == 1) return 1;
if(dp[l][r] == -1) return 0;
for(int i = l + 1; i < r - 1; i++) //i < r - 1是因为给xy型y至少含有两个相同字母,预留出倒数第二个,所以能进入此循环长度必然>=4
{
if(str[i] == str[l])
{
if(dfs(l, i) && dfs(i + 1, r))
return dp[l][r] = 1;
}
}
if(str[l] == str[r]) //AxA型
{
if(dfs(l + 1, r - 1))
return dp[l][r] = 1;
for(int i = l + 1; i < r; i++)
{
if(str[i] == str[l]) //AxAyA型
{
if(dfs(l + 1, i - 1) && dfs(i + 1, r - 1)) //eg:AABBBAA中的BBB奇数个按照此dfs写法只能进入AxAyA匹配,因为dfs终点为l == r;偶数个的可以进入xy或AxA型,dfs终点必然为l > r
return dp[l][r] = 1;
}
}
}
dp[l][r] = -1; //注意此题dp和return值有所区分,一个不可达为-1,一个为0
return 0;
}
int main()
{
while(scanf("%s", str) != EOF)
{
memset(dp, 0, sizeof(dp));
int len = strlen(str);
bool flag = dfs(0, len - 1);
if(flag)
cout << "solvable" << endl;
else
cout << "unsolvable" << endl;
}
return 0;
}