codeforces 154 A DP

来源:互联网 发布:ceic全球经济数据库 编辑:程序博客网 时间:2024/05/21 07:53

蛮有意思的一个题

给你一个字符串,再给你k对字符

要求删掉一些字符使得字符串中不存在相邻的字符是这k对中的某一对

 

首先如果一个字符只出现在k对中的某一对中,那么可以贪心做

因为不会出现如下情况了 :

aaaabbbcccc 

2

ab

ac

即不会出现删了之后前面的字符缩进来还会出现矛盾

 

但是当可以出现这种情况怎么办

DP就派上用场了

dp[i][j]表示前i个字符处理完了之后最后一个字符为(j+'a')的最小需要删掉的字符

那么到某个i位置的时候,首先不管它和前面留下来的最后一个字符有没有矛盾,都可以将它删除掉

如果没有矛盾,我们还可以将状态转移为以当前字符结尾

View Code
#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<iostream>#include<cmath>#include<cstdlib>#include<vector>#include<set>#include<map>#include<queue>#include<stack>using namespace std;const int inf = ~0u>>2;int flag[27][27];int dp[100010][27];char s[100010];int main(){    int k;    string op;    while(scanf("%s",s+1)!=EOF)    {        cin>>k;        memset(flag,0,sizeof(flag));        fill(dp[0],dp[100001],inf);        while(k--)        {            cin>>op;            flag[op[0]-'a'][op[1]-'a']=1;            flag[op[1]-'a'][op[0]-'a']=1;        }        dp[0][26]=0;        int len=strlen(s+1);        for(int i=1;i<=len;i++)        {            for(int j=0;j<=26;j++)    if(dp[i-1][j]!=inf)            {                int k=s[i]-'a';                dp[i][j]=min(dp[i][j],dp[i-1][j]+1);//将第i个字符删掉                if(!flag[j][k])                {                    dp[i][k]=min(dp[i][k],dp[i-1][j]);//没有矛盾,可以不删                }            }        }        int ans=inf;        for(int i=0;i<=26;i++)        {            if(dp[len][i]<ans)            {                ans=dp[len][i];            }        }        printf("%d\n",ans);    }    return 0;}

 

原创粉丝点击