HDU 4628 Pieces 解题报告

来源:互联网 发布:网络安全技术是什么 编辑:程序博客网 时间:2024/06/06 01:37

题目

2013 暑假多校训练 3

题意:

一个字符串,每次可以删掉一个子序列,且这个子序列必须构成回文串,求全部删完的最少次数。

题解:

枚举要删除的子序列,剩下的继续删除,记下每个部分的最少删除次数。


代码写得很挫……

//Time:125ms//Memory:560KB#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <map>#define MAXN 20#define MAXM (1<<16)#define FI first#define SE second#define INF 1000000007#define MP(x,y) make_pair((x),(y))using namespace std;struct _node{    char str[MAXN];    int pos[MAXN];    int len;};int pre[MAXM];int dp[MAXN][MAXN];pair<int,int> fa[MAXN][MAXN];void cal(char *s,int len,int x,int y){    for(int i=x;i>=0;--i)        for(int j=y;j<len;++j)            if(i!=x||j!=y)            {                dp[i][j]=0;                if(i<x&&dp[i+1][j]>dp[i][j])    dp[i][j]=dp[i+1][j],fa[i][j]=MP(i+1,j);                if(j>y&&dp[i][j-1]>dp[i][j])    dp[i][j]=dp[i][j-1],fa[i][j]=MP(i,j-1);                if(i<x&&j>y&&s[i]==s[j])                    if(dp[i+1][j-1]+2>dp[i][j])                        dp[i][j]=dp[i+1][j-1]+2,fa[i][j]=MP(0,-1);            }}int solve(_node no){    _node tno;    int ans=INF,tmp;    pair<int,int> now;    bool vi[MAXN]={0};    for(int i=0;i<no.len;++i)    {        for(int j=i;j<no.len;++j)        {            if(no.str[j]!=no.str[i])    continue;            memset(dp,0,sizeof(dp));            memset(vi,0,sizeof(vi));            dp[i][j]=(i!=j?2:1);            fa[i][j]=MP(-1,-1);            cal(no.str,no.len,i,i);            now=MP(0,no.len-1);            vi[i]=vi[j]=1;            while(now.FI!=-1)            {                if(fa[now.FI][now.SE]==MP(0,-1)) vi[now.FI]=1,vi[now.SE]=1,++now.FI,--now.SE;                else    now=fa[now.FI][now.SE];            }            tmp=0;            tno.len=0;            for(int i=0;i<no.len;++i)                if(!vi[i])                {                    tno.str[tno.len]=no.str[i];                    tno.pos[tno.len++]=no.pos[i];                    tmp|=1<<no.pos[i];                }            if(pre[tmp]<INF)                ans=min(ans,1+pre[tmp]);            else    ans=min(ans,1+solve(tno));        }    }    tmp=0;    for(int i=0;i<no.len;++i)        tmp|=1<<(no.pos[i]);    pre[tmp]=min(pre[tmp],ans);    return ans;}int main(){    //freopen("/home/moor/Code/input","r",stdin);    int ncase;    _node no;    scanf("%d",&ncase);    while(ncase--)    {        scanf("%s",no.str);        memset(pre,0x3f,sizeof(pre));        pre[0]=0;        no.len=strlen(no.str);        for(int i=0;i<no.len;++i)   no.pos[i]=i;        printf("%d\n",solve(no));    }    return 0;}


原创粉丝点击