bzoj1055玩具取名

考虑区间dp

dp[i][j][k]表示区间[i,j]可不可以缩成字符k

dp[i][j][k]=-1表示没算过 0表示不可以 1表示可以

dp[i][j][k]=1当且仅当

dp[l][j][a]=1 且 dp[j+1][r][b]=1且ab可以转化成k

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
    return x*f;
}
const char name[]={'W','I','N','G'};
int hash[255];
int dp[205][205][4];
char a[30][30][2];
int W[5];
char str[1000];
bool dfs(int l,int r,int k)
{
    if(l==r)return str[l]==name[k];
    int &res=dp[l][r][k];
    if(~res)return res;
    for(int i=1;i<=W[k];i++)
    {
        for(int j=l;j<=r-1;j++)
        {
            if(dfs(l,j,hash[a[k][i][0]]) && dfs(j+1,r,hash[a[k][i][1]]))
            return res=1;
        }
    }
    return res=0;
}
int main()
{
    memset(dp,-1,sizeof(dp));
    hash['W']=0,hash['I']=1,hash['N']=2,hash['G']=3;
    for(int i=0;i<4;i++)W[i]=read();
    for(int i=0;i<4;i++)
        for(int j=1;j<=W[i];j++)
            scanf("%s",a[i][j]);
    
    scanf("%s",str+1);
    int len=strlen(str+1);
    int flag=0;
    for(int i=0;i<4;i++)
    {
        if(dfs(1,len,i))
        {
            flag=1;
            printf("%c",name[i]);
        }
    }
    if(!flag)printf("The name is wrong!");
    return 0;
}
View Code

 

posted @ 2017-11-01 14:02  探险家Mr.H  阅读(135)  评论(0编辑  收藏  举报