HDU3109: Worms(字符串变换类 DP)

Posted hua-dong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3109: Worms(字符串变换类 DP)相关的知识,希望对你有一定的参考价值。

pro:开始有一个字母虫,然后字母虫在每一天可以选择自己身上的部分字母变换,变换规则形如A->BC。 现状给定最终字母虫的字符串,求最少用了多少天。

如有规则A->BC,B->AC,C->AB;则ACAB可以见过三天(A-BC-ACC-ACAC)或者两天(A-BC-ACAB)得来。 规则不超过80,字符串长度不超过50;

sol:dp[i][j][p]表示,最开始只有字母p,变换到[i,j]区间的最小天数。

         显然初始:dp[i][i][x]=c[i]==x?0:inf;

         其他:       dp[i][j][x]=min(dp[i][k][p],dp[k+1][j][q]+1);  当且当存在规则x->pq;

经验:在倒推比较难的情况下,我们表示的状态可以是最初状态。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=52;
char c[maxn],s[maxn*2][5];
int dp[maxn][maxn][maxn];
vector<int>A[20],B[20];
int main()

    int N,L;
    while(~scanf("%d",&N))
        if(!N) break;
        rep(i,0,19) A[i].clear(),B[i].clear();
        rep(i,1,N)
             scanf("%s",s[i]);
             A[s[i][0]-A].push_back(s[i][1]-A);
             B[s[i][0]-A].push_back(s[i][2]-A);
        
        scanf("%s",c+1); L=strlen(c+1);
        rep(i,1,L) rep(j,i,L) rep(k,0,19) dp[i][j][k]=L+1;
        rep(i,1,L) dp[i][i][c[i]-A]=0;
        rep(i,1,L) 
            rep(l,1,L-i)
                int r=l+i;
                rep(p,0,19)
                    rep(k,l,r-1)
                        for(int t=0;t<A[p].size();t++)
                            dp[l][r][p]=min(dp[l][r][p],max(dp[l][k][A[p][t]],dp[k+1][r][B[p][t]])+1);
                        
                    
                
            
        
        int ans=L+1;
        rep(i,0,19) if(dp[1][L][i]!=-1) ans=min(ans,dp[1][L][i]);
        if(ans==L+1) ans=-1;
        printf("%d\n",ans);
    
    return 0;

 

以上是关于HDU3109: Worms(字符串变换类 DP)的主要内容,如果未能解决你的问题,请参考以下文章

HDU5945 Fxx and game 单调队列优化dp

[HDU4867]Xor (线段树分治+类数位dp)

hdu 1159(DP+字符串最长公共序列)

hdu2476(区间dp)

[HDU6155]Subsequence Count(线段树+矩阵)

HDU 1041[Computer Transformation] 递推 高精度