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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章