hdu 4628 Pieces (状态压缩dp)

题意:给你几个字符串,你每次删除的字母要按顺序看是一个回文串。求最少几次就可以把它删完。

思路:状态压缩dp。写个函数判断一个状态含有的1是否按顺序对应字符串的位置的字母是一个回文串。预处理所有是回文串的状态,否则会TLE。然后直接枚举删之前的状态和删完之后的状态,判断删的是不是回文串。

第一次用异或^,具体见代码注释,应该不难理解。

AC代码:

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
const int mo=1e8;
const int mx=1<<16;
const int inf=0x3f3f3f3f;
int n,m,ans,k,T,num;
char s[20];
int dp[mx];
int zt[mx];
bool b[mx];
void init()
{
memset(dp,-1,sizeof(dp));
memset(b,0,sizeof(b));
    num=0;
}
bool jud(int i)
{
if(i==0) return 1;
int j=0;
int k=n-1;
while(j<k)//直接暴力判断是不是回文串
   {
    while(!(1<<j&i)) {j++;}
    while(!(1<<k&i)) {k--;}
    if(s[j]!=s[k]) return 0;
    {j++;}
        {k--;}
}
return 1;
}
int main() {
    int t,i,j,k,l,q,x,y,h;
    int cas=1,flag,f1;
     while(scanf("%d",&T)!=EOF)
    {
    while(T--){
        scanf("%s",s);
        n=strlen(s);
        m=1<<n;
        init();
        for(i=0;i<m;i++) if(jud(i)) b[i]=1;//一定要预处理出合法的状态
        dp[0]=0;
        for(i=0;i<m;i++)
        {
            for(k=(i+1)|i;k<m;k=(k+1)|i)//枚举包含i状态的状态,因为你删除原串中的回文串就相当于把i状态的某些位置的0变成1,也就是变成包含i状态的k状态
            {
            if (b[k^i]&&dp[i]!=-1)//k^i就是你删除的那个串,想想是不是
            {if (dp[k]<0)dp[k]=dp[i]+1;
            else dp[k]=min(dp[k],dp[i]+1);
            }
        }
    }
      printf("%d\n",dp[m-1]);
    }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值