Live2d Test Env

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;
}

 

posted @ 2019-06-07 09:31  nimphy  阅读(344)  评论(0编辑  收藏  举报