码迷,mamicode.com
首页 > 其他好文 > 详细

P4290 [HAOI2008]玩具取名

时间:2019-09-03 09:33:16      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:++   tle   nbsp   左右   字符串   cst   blank   read   def   

传送门

$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]玩具取名

标签:++   tle   nbsp   左右   字符串   cst   blank   read   def   

原文地址:https://www.cnblogs.com/LLTYYC/p/11450833.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!