P4290 [HAOI2008]玩具取名

Posted lltyyc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4290 [HAOI2008]玩具取名相关的知识,希望对你有一定的参考价值。

传送门

$dp$

设 $f[i][j][k]$ 表示初始为 $k$ 时,能否得到 $[i,j]$ 这一段子串

设 $pd[i][j][k]$ 表示长度为二的字符串 $ij$ 能否由 $k$ 得到

然后枚举左右区间转移:有

$f[i][j][k]=[f[i][p][x]=1]\ and\ [f[p+1][j][y]=1]\ and\ [pd[x][y][k]=1]$

边界 $f[i][i][k]=[a[i]=k]$

然后直接记忆化搜索

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()

    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9)  if(ch==-) f=-1; ch=getchar(); 
    while(ch>=0&&ch<=9)  x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); 
    return x*f;

int n[7],a[207],m;
int pd[7][7][7];
char s[207];
bool f[207][207][7],vis[207][207][7];
inline int F(char s)

    if(s==W) return 1;
    if(s==I) return 2;
    return s==N ? 3 : 4;

inline char DF(int x)

    if(x==1) return W;
    if(x==2) return I;
    return x==3 ? N : G;

bool dfs(int l,int r,int x)

    if(l==r&&a[l]==x) return 1;
    if(vis[l][r][x]) return f[l][r][x];
    vis[l][r][x]=1; bool &T=f[l][r][x];
    for(int i=l;i<r;i++)
        for(int j=1;j<=4;j++)
            for(int k=1;k<=4;k++)
                if(pd[j][k][x]&&dfs(l,i,j)&&dfs(i+1,r,k))  T=1; break; 
    return T;

int main()

    for(int i=1;i<=4;i++) n[i]=read();
    for(int i=1;i<=4;i++)
        for(int j=1;j<=n[i];j++)
        
            scanf("%s",s);
            pd[F(s[0])][F(s[1])][i]=1;
        
    scanf("%s",s+1); m=strlen(s+1);
    for(int i=1;i<=m;i++) a[i]=F(s[i]);
    bool flag=0;
    for(int i=1;i<=4;i++)
        if(dfs(1,m,i)) printf("%c",DF(i)),flag=1;
    if(!flag) printf("The name is wrong!");
    printf("\n");
    return 0;

 

以上是关于P4290 [HAOI2008]玩具取名的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1055[HAOI2008]玩具取名 区间dp

bzoj1055[HAOI2008]玩具取名

bzoj1055 [HAOI2008]玩具取名

BZOJ 1055 [HAOI2008]玩具取名

bzoj1055: [HAOI2008]玩具取名(dp)

玩具取名「HAOI2008」