POJ 3821 Clickomania

来源:互联网 发布:unity3d 上海 外包 编辑:程序博客网 时间:2024/06/05 09:49

http://poj.org/problem?id=3821

遍历搜索:用数组保存中间结果(类似动态规划思想)

几种情况:串AxAyAz

1. Ax:最开始的相同字母串A可以消掉,判断x,可消返回真,否则继续;

2. AxAz:首字母串肯定要与后面的字母串合起来一起消,问题变为判断AxA和yAz(可能不含A)两个子串;

3. AxA: 输入串或2都可能产生串AxA的形式,只要判断x,或者将AxA转化成AyAzA形式,判断y和z串

4. Ax:非上述情况,x不含A,返回false

总体思路:

1.处理串:对于串中相邻的相同字母合为一个,tag[]来标识该字母是单个还是多个(减少串长降低计算时间)

2.查找每个字母的下一个相同字母的位置,用rig[i]表示串中i位置的字母的相同的右边的字母位置,没有为-1

3.递归搜索串是否可消,并用sov[i][j]表示串中i到j的子串是否可消来保留中间结果减少重复搜索,递归搜索的思路如上对串的处理。

 

code:

#include <iostream>
#include <string>
using namespace std;
#define MAX 151
int sov[MAX][MAX],rig[MAX];
bool tag[MAX];
bool search(int low,int up)
{
//    printf("%d %d = %d\n",low,up,sov[low][up]);
    if(sov[low][up] != -1)
        return sov[low][up]==0?false:true;
    if(low > up)return true;
    if(tag[low]){  //情况1
    //    printf("%d\n",low);
        sov[low+1][up] = search(low+1,up);
        if(sov[low+1][up])return true;
    }
    int i,j;
    i = rig[low];
//    printf("%d %d\n",low,i);
    while(i != -1 && i < up)   //情况2
    {
        sov[low][i] = search(low,i);
        sov[i+1][up] = search(i+1,up);
        if(sov[low][i] && sov[i+1][up])return true;
        i = rig[i];
    }
    if(i == -1 || i > up)return false;
    if(i == up)   //情况3
    {
        sov[low+1][up-1] = search(low+1,up-1);
        if(sov[low+1][up-1])return true;
        for(j = rig[low];j < up;j = rig[j])
        {
            sov[low+1][j-1] = search(low+1,j-1);
            sov[j+1][up-1] = search(j+1,up-1);
            if(sov[low+1][j-1] && sov[j+1][up-1])return true;
        }
    }
    return false;
}
int main()
{
    char s[MAX];
    int i,j,n,vis[30];
    while(scanf("%s",&s)!=EOF)
    {
        memset(tag,0,sizeof(tag));
        j = 0;
        for(i = 1;i < strlen(s);i ++)   //思路1
        {
            if(s[i] == s[j])
                tag[j] = true;
            else
                s[++j] = s[i];
        }
        n = j+1;
        memset(rig,-1,sizeof(rig));
        memset(vis,-1,sizeof(vis));
        for(i = 0; i < n;i ++)   //思路2
        {
            if(vis[s[i]-'A'] == -1)
                vis[s[i]-'A'] = i;
            else{
                rig[vis[s[i]-'A']] = i;
                vis[s[i]-'A'] = i;
            //    left[i] = vis[s[i]-'A'];
            }
        }
        memset(sov,-1,sizeof(sov));
        for(i = 0;i < n;i ++)
            sov[i][i] = tag[i];
        if(search(0,n-1))printf("solvable\n");  //思路3
        else printf("unsolvable\n");
    }
    return 0;
}