BZOJ1055: [HAOI2008]玩具取名

BZOJ1055: [HAOI2008]玩具取名

区间Dp

题解:

f[l][r][x]表示 [l,r] 区间能否变成 x 这个字母。

转移:枚举最后一次合并的划分点,枚举x的每一种变形规则,看看左右两边是否都可以变成变形则需要的字母。

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <map>
#define MP make_pair
#define D(x) cout<<#x<<" = "<<x<<"  "
#define E cout<<endl
using namespace std;
typedef pair<int,int> pii;
const int N = 205;

map<char,int> dic; map<int,char> redic;
int atot,btot,ctot,dtot;
vector<pii> edge[5];
int f[N][N][5]; 
int n; char str[N];

void input(){
    cin>>atot>>btot>>ctot>>dtot;
    char tp[5];
    for(int i=1;i<=atot;i++){
        scanf("%s",tp);
        edge[1].push_back(MP(dic[tp[0]],dic[tp[1]]));
    }
    for(int i=1;i<=btot;i++){
        scanf("%s",tp);
        edge[2].push_back(MP(dic[tp[0]],dic[tp[1]]));
    }
    for(int i=1;i<=ctot;i++){
        scanf("%s",tp);
        edge[3].push_back(MP(dic[tp[0]],dic[tp[1]]));
    }
    for(int i=1;i<=dtot;i++){
        scanf("%s",tp);
        edge[4].push_back(MP(dic[tp[0]],dic[tp[1]]));
    }
    scanf("%s",str+1); n=strlen(str+1);
}

int dp(int l,int r,int x){
//  D(l); D(r); D(x); E;
    int &ans = f[l][r][x];
    if(ans!=-1) return ans;
    if(l==r){ return ans=(dic[str[l]]==x); }
    for(int i=l;i<r;i++){
        for(int j=0;j<edge[x].size();j++){
            pii t=edge[x][j];
            if(dp(l,i,t.first) && dp(i+1,r,t.second)){
                return ans=1;
            }
        }
    }
    return ans=0;
}

void init(){
    memset(f,-1,sizeof(f));
    dic['W']=1; dic['I']=2; dic['N']=3; dic['G']=4;
    redic[1]='W'; redic[2]='I'; redic[3]='N'; redic[4]='G';
}

int main(){
    freopen("a.in","r",stdin);
    init(); input();
    int can=0;
    for(int i=1;i<=4;i++){
        if(dp(1,n,i)){ cout<<redic[i]; can++; }
    }
    if(!can){ puts("The name is wrong!"); }
    else cout<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值