HDU 4628——Pieces

题目链接:

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

 

题目大意:

给出一个字符串,每次你可以擦除一个回文子串,问至少需要多少步可以将该字符串全部擦除。

 

解题思路:

由于字符串的长度最多是16,所以可以采用状态压缩来解这个题目。

dp[i][j]:表示第i步时,状态j是否出现。

 

源代码:

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
char ch[20];
int dp[20][70000];
string s;
int state[70000];
int cnt;
int ok(string t)    //判断字符串是否回文
{
    int i,j;
    i=0;
    j=t.length()-1;
    while(i<j)
    {
        if(t[i]!=t[j])  return 0;
        else
        {
            i++; j--;
        }
    }
    return 1;
}
string zifu(int k)      //将状态数转成对应的字符串
{
    int len;
    string s1;
    len=s.length();
    s1="";
    for(int i=0;i<len;i++)
    {
        if(k%2==1)   s1+=s[i];
        k=k/2;
    }
    return s1;
}
void init(string s)     //找出所有的有效状态
{
    int k,len,i;
    string s1;
    len=s.length();
    k=(1<<len)-1;       //所有状态的总个数
    memset(state,0,sizeof(state));
    cnt=0;
    for(i=1;i<=k;i++)
    {
        s1=zifu(i);
        if(ok(s1))
        {
            state[cnt++]=i;
        }
    }
    return;
}
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    freopen("in.txt","r",stdin);
    int cs,i,d,j,k;
    scanf("%d",&cs);
    while(cs--)
    {
        scanf("%s",ch);
        s=ch;
        i=s.length();
        d=(1<<i)-1;
        init(s);
        sort(state,state+cnt,cmp);
        if(state[0]==d)
        {
            printf("1\n");
            continue;
        }

        memset(dp,0,sizeof(dp));
        //枚举第一行出现的有效状态
        for(i=0;i<cnt;i++)
        {
            dp[1][state[i]]=1;
        }
        int flag=0;
        for(i=2;;i++)               //枚举接下来的行状态
        {
            for(j=1;j<=d;j++)       //枚举上一行的状态
            {
                if(dp[i-1][j]==0)   continue;
                for(k=0;k<cnt;k++)  //枚举当前行可以擦除的状态
                {
                    if((state[k]&j)==0)     //所取状态与已得状态不冲突
                        dp[i][state[k]+j]=1;
                }
                if(dp[i][d]==1)
                {
                    printf("%d\n",i);
                    flag=1;
                    break;
                }
            }
            if(flag)    break;
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章