bzoj1055 [HAOI2008]玩具取名 dp

Description


  某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后
他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。
现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。

100%数据满足Len<=200,W、I、N、G<=16

Solution


一开始还以为是什么奇怪的图论题,我果然菜啊

设f[i,j,k]表示i到j能否用k表示,然后暴力转移即可

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fi first
#define se second

typedef std:: pair <int,int> pair;
const int N=205;

bool f[N][N][4];
char str[N];
pair a[N][N];
int cnt[N];

int get(char x) {
    if (x=='W') return 0;
    if (x=='I') return 1;
    if (x=='N') return 2;
    if (x=='G') return 3;
}

int main(void) {
    rep(i,0,3) scanf("%d",&cnt[i]);
    rep(i,0,3) {
        rep(j,1,cnt[i]) {
            char ch[2]; scanf("%s",ch);
            a[i][j]=pair(get(ch[0]),get(ch[1]));
        }
    }
    scanf("%s",str+1); int n=strlen(str+1);
    rep(i,1,n) f[i][i][get(str[i])]=1;
    rep(len,1,n) {
        rep(i,1,n-len) {
            int j=i+len;
            rep(k,0,3) rep(l,i,j) {
                if (f[i][j][k]) break;
                rep(t,1,cnt[k]) {
                    if (f[i][j][k]) break;
                    f[i][j][k]|=f[i][l][a[k][t].fi]&f[l+1][j][a[k][t].se];
                }
            }
        }
    }
    if (f[1][n][0]) putchar('W');
    if (f[1][n][1]) putchar('I');
    if (f[1][n][2]) putchar('N');
    if (f[1][n][3]) putchar('G');
    if (!f[1][n][0]&&!f[1][n][1]&&!f[1][n][2]&&!f[1][n][3]) {
        puts("The name is wrong!");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/80718003
今日推荐