• bzoj 1055: [HAOI2008]玩具取名


    Description

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

    Input

      第一行四个整数W、I、N、G。表示每一个字母能由几种两个字母所替代。接下来W行,每行两个字母,表示W可
    以用这两个字母替代。接下来I行,每行两个字母,表示I可以用这两个字母替代。接下来N行,每行两个字母,表示N
    可以用这两个字母替代。接下来G行,每行两个字母,表示G可以用这两个字母替代。最后一行一个长度不超过Len的
    字符串。表示这个玩具的名字。

    Output

      一行字符串,该名字可能由哪些字母变形而得到。(按照WING的顺序输出)如果给的名字不能由任何一个字母
    变形而得到则输出“The name is wrong!”

    Sample Input

    1 1 1 1
    II
    WW
    WW
    IG
    IIII

    Sample Output

    IN

    HINT

    W可以变成II所以IIII可以缩成WW IN均能变成WW所以WW又可以缩成I或者N 所以最终答案应该按照“WING”的顺序

    输出IN 

    [数据范围]

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

    Source

     算是最基础的区间dp类型了,设dp[i][j][k],表示[i,j]能否由k变来;

    题目里面说明了每个字母都可以由两个字母变来,那么我们容易想到把[i,j]枚举断点分为两个区间,然后合并两个区间的信息,就是n^3的那种区间dp;

    实现的话,区间dp最好都是写记忆化搜索,这样就不会有转移顺序的问题;

    //MADE BY QT666
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N=300;
    bool dp[N][N][5],bj[N][N][5];
    struct data{
        int x,y;
    };
    vector<data> g[N];
    char ch[N];
    int s[N];
    bool dfs(int l,int r,int p){
        if(l==r){
    	bj[l][r][p]=1;
    	dp[l][r][p]=(s[l]==p);
    	return dp[l][r][p];
        }
        if(bj[l][r][p]) return dp[l][r][p];
        for(int k=l;k<r;k++){
    	for(int i=0;i<g[p].size();i++){
    	    dp[l][r][p]|=(dfs(l,k,g[p][i].x)&&dfs(k+1,r,g[p][i].y));
    	    if(dp[l][r][p]) break;
    	}
    	if(dp[l][r][p]) break;
        }
        bj[l][r][p]=1;return dp[l][r][p];
    }
    void read(int xh,int sz){
        for(int i=1;i<=sz;i++){
    	scanf("%s",ch+1);int x,y;
    	if(ch[1]=='W') x=1;
    	if(ch[1]=='I') x=2;
    	if(ch[1]=='N') x=3;
    	if(ch[1]=='G') x=4;
    	if(ch[2]=='W') y=1;
    	if(ch[2]=='I') y=2;
    	if(ch[2]=='N') y=3;
    	if(ch[2]=='G') y=4;
    	g[xh].push_back((data){x,y});
        }
    }
    int main(){
        int w,i,n,g;
        scanf("%d%d%d%d",&w,&i,&n,&g);
        read(1,w);read(2,i);read(3,n);read(4,g);
        scanf("%s",ch+1);int len=strlen(ch+1);
        for(int i=1;i<=len;i++){
    	if(ch[i]=='W') s[i]=1;
    	if(ch[i]=='I') s[i]=2;
    	if(ch[i]=='N') s[i]=3;
    	if(ch[i]=='G') s[i]=4;
        }
        int flg=0;
        for(int i=1;i<=4;i++){
    	if(dfs(1,len,i)){
    	    if(i==1) cout<<"W";
    	    if(i==2) cout<<"I";
    	    if(i==3) cout<<"N";
    	    if(i==4) cout<<"G";
    	    flg=1;
    	}
        }
        if(!flg) puts("The name is wrong!");
        return 0;
    }
    
  • 相关阅读:
    2.2 图像分类-线性分类
    2.1 图像分类-K最近邻算法
    2 图像分类-数据驱动方法
    Week6
    R-CNN 原理详解
    1.2 课程介绍-课程后勤
    012_04Thread+Handler实例应用之号码归属地查询
    010_04用户登录(用户名,密码交给服务器并验证)
    010_03HTML源码查看器
    010_02带缓存的图片查看器
  • 原文地址:https://www.cnblogs.com/qt666/p/7667914.html
Copyright © 2020-2023  润新知