HDU3427 Clickomania【记忆化搜索】【区间DP】

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3427


题目大意:

Clickomania(彩球消除)是一款游戏,有几种颜色不同的方块排成一列。每次可以将一段连续的

颜色相同的方块消除掉,消除后原本这段方块两端的方块连接在一起,比如:ABBBA,将中间

BBB消除后,就变成了AA。现在给你一段字符串,不同的字符代表不同的颜色,那么问题来

了:能不能将整个字符串消除完。


思路:

字符串的题目。本来感觉题目没有思路、无从下手,所幸题目中给了能够消除的所有情况:xy,

AxA,AxAyA三种情况。x和y表示可以消除的部分。把整个字符串看做一个区间,分解区间为

多个能够消除的子区间,直到不能分解为止。那么,如果还存在无法消除的区间,那么整字符

串就不能够消除完。如果子区间都能消除掉,那么整个字符串就能消除完。那么,接下来就是具

体实现过程了。

s[]数组来保存字符串,dp[i][j]表示第i个字符到第j个字符是否能被消除,为1则能被消除。用记忆

化搜索的方法判断区间[Left,Right]是否满足xy,AxA,AxAyA三种消除方式,并递归分解解决。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

char s[160];
int dp[160][160];

bool solve(int Left,int Right)
{
    if(Left > Right || dp[Left][Right] == 1)
        return true;
    if(Left == Right || dp[Left][Right] == -1)
        return false;

    for(int i = Left+1; i <= Right-2; ++i)      //xy型
    {
        if(solve(Left,i) && solve(i+1,Right))
        {
            dp[Left][Right] = 1;
            return true;
        }
    }

    if(s[Left] == s[Right])
    {
        if(solve(Left+1,Right-1))               //AxA型
        {
            dp[Left][Right] = 1;
            return true;
        }
        for(int i = Left+1; i <= Right-1; ++i)  
        {
            if(s[i] == s[Left])
            {
                if(solve(Left+1,i-1) && solve(i+1,Right-1)) //AxAyA型
                {
                    dp[Left][Right] = 1;
                    return true;
                }
            }
        }
    }
    dp[Left][Right] = -1;
    return false;
}
int main()
{
    while(cin >> s)
    {
        memset(dp,0,sizeof(dp));
        int len = strlen(s);

        bool ans = solve(0,len-1);
        if(ans)
            printf("solvable\n");
        else
            printf("unsolvable\n");
    }

    return 0;
}


你可能感兴趣的:(HDU3427 Clickomania【记忆化搜索】【区间DP】)