Pieces(HDU-4628)

本文介绍了一种使用状态压缩动态规划(状压DP)解决特定字符串操作问题的方法。在一个长度不超过16的字符串中,目标是在最少的步骤内通过去除可形成回文的子序列来清空整个序列。文章详细解释了如何利用状态压缩和动态规划减少计算复杂度,并给出了完整的源代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description

You heart broke into pieces.My string broke into pieces.But you will recover one day,and my string will never go back. 
Given a string s.We can erase a subsequence of it if this subsequence is palindrome in one step. We should take as few steps as possible to erase the whole sequence.How many steps do we need? 
For example, we can erase abcba from axbyczbea and get xyze in one step.

Input 

The first line contains integer T,denote the number of the test cases. Then T lines follows,each line contains the string s (1<= length of s <= 16).

T<=10.

Output

For each test cases,print the answer in a line.

Sample Input

2
aa
abb

Sample Output

1
2

题意:给一个字符串,每次可以在字符串中选取任意个能组成回文串的字符(可为不连续的)去掉,单个字符亦视为回文,

思路:状压DP

字符串长度<=16,可以考虑枚举所有状态,将每个串压缩成一个状态,用0、1分别表示字符串某位置的字符去掉、保留,比较状态和子状态与相应的状态,进行状态转移取小值即可

Source Program

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 20
#define MOD 10007
#define E 1e-6
#define LL long long
using namespace std;
char str[N];
int sta[N];
int dp[1<<N];
int len;
int init(int x){
    int head=0;
    memset(sta,0,sizeof(sta));

    for(int i=0;i<=len;i++)
        if(x&(1<<i))
            sta[head++]=i;
    head--;
    for(int i=0;i<head/2;i++)//从中点向两端看,判断是否是回文
        if(str[sta[i]]!=str[sta[head-i]])//若不是回文,则返回是回文的状态x的长度
            return head;
    return 1;
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--){
        memset(dp,0,sizeof(dp));
        scanf("%s",str);

        len=strlen(str);
        int allState=1<<len;
        for(int i=1;i<allState;i++){//枚举所有状态
            dp[i]=init(i);//对每一状态初始化
            for(int j=i;j>0;j=(j-1)&i)
                dp[i]=min(dp[i],dp[j]+dp[j^i]);
        }
        printf("%d\n",dp[allState-1]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值