HDU 4628 Pieces(状态压缩+记忆化搜索)

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

题意:给个字符窜,每步都可以删除一个字符窜,问最少用多少步可以删除一个字符窜
分析:状态压缩+记忆化搜索
         先打表,把每一个构成回文的字符窜的状态i都存到一个ss数组中。然后再判断某一个回文是否能
够删除,判断条件是(ans|i)==ans,ans或i等于ans,这个说明i没有多余的1

//pragma comment(linker, "/STACK:102400000,102400000")

#include<stdio.h>

#include<string.h>

#include<algorithm>

using namespace std;

const int MN=70000;

int dp[MN];

char str[MN];

char tmp[20];

int ss[MN];

int cas;



bool judge(int n)//判断回文

{

    for(int i=0;i<n/2;i++)

    {

        if(tmp[i]!=tmp[n-i-1]) return false;

    }

    return true;

}



int work(int t)

{

    int cnt=0;

    while(t)

    {

        t/=2;

        cnt++;

    }

    return cnt;

}



int DFS(int ans)

{

    if(dp[ans]!=-1) return dp[ans];

    if(ans==0) return 0;

    int &res=dp[ans];

    res=work(ans);

    for(int i=0;i<cas;i++)

    {

        if((ss[i]|ans)==ans)

        {

            int tmp=ans^ss[i];

            res=min(res,DFS(tmp)+1);

        }

    }

    return res;

}



int main()

{

    int i,j,tot,T;

    scanf("%d",&T);

    while(T--)

    {

        memset(dp,-1,sizeof(dp));

        cas=0;

        scanf("%s",str);

        int len=strlen(str);

        for(i=1;i<=(1<<len)-1;i++)

        {

            int cnt=0;

            for(j=0;j<len;j++)

            {

                if((1<<j)&i)

                {

                    tmp[cnt++]=str[j];

                }

            }

            if(judge(cnt)) ss[cas++]=i;

        }

        printf("%d\n",DFS((1<<len)-1));

    }

    return 0;

}
View Code

 

你可能感兴趣的:(HDU)