• bzoj1055 [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

    分析:
    1A✿✿ヽ(°▽°)ノ✿
    说白了,就是一道合并游戏
    诶。。。好像是石子合并的加强版
    f[i][j][0/1/2/3]
    表示从i到j的字符串能不能替换成WING

    tip

    对于状态的处理注意一下
    直接把字母转化成了数字,计入zt(zhuangtai)数组

    int get(char a)
    {
        if (a=='W') return 0;
        else if (a=='I') return 1;
        else if (a=='N') return 2;
        else return 3;
    }
    
    void cl(int bh,int z)
    {
        int x,y;
        x=get(w[0]);
        y=get(w[1]); 
        zt[bh][z][0]=x;
        zt[bh][z][1]=y;
    }

    在转移的时候
    这里写图片描述
    注意 if (!f[i][j][0]) 的判断,
    不然会出现明明这个状态可以通过一种方式到达,
    但是另一种方式到达不了,导致f[i][j][]状态能否到达判断失误

    因为只是一个判定性的问题,所以这里f的类型我定义的是bool
    节省空间(没这个必要,但要养成节约的好习惯)

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int nn=210;
    char s[nn],w[5];
    int W,I,N,G;
    int mp[5][5],zt[5][20][2];
    bool f[nn][nn][5],flag=0;
    
    int get(char a)
    {
        if (a=='W') return 0;
        else if (a=='I') return 1;
        else if (a=='N') return 2;
        else return 3;
    }
    
    void cl(int bh,int z)
    {
        int x,y;
        x=get(w[0]);
        y=get(w[1]); 
        zt[bh][z][0]=x;
        zt[bh][z][1]=y;
    }
    
    void doit()
    {
        int i,j,k,q,r1,r2;
        int l=strlen(s);
        for (i=0;i<l;i++)
             f[i][i][get(s[i])]=1;
        for (i=l-2;i>=0;i--)
            for (j=i+1;j<l;j++)
                for (k=i;k<j;k++)
                {
                    for (q=1;q<=W;q++) 
                    {
                        r1=zt[0][q][0];r2=zt[0][q][1];  //两个可以转移的字母 
                        if (!f[i][j][0]) f[i][j][0]=f[i][k][r1]&f[k+1][j][r2];
                    }
                    for (q=1;q<=I;q++) 
                    {
                        r1=zt[1][q][0];r2=zt[1][q][1];  //两个可以转移的字母 
                        if (!f[i][j][1]) f[i][j][1]=f[i][k][r1]&f[k+1][j][r2];
                    }
                    for (q=1;q<=N;q++) 
                    {
                        r1=zt[2][q][0];r2=zt[2][q][1];  //两个可以转移的字母 
                        if (!f[i][j][2]) f[i][j][2]=f[i][k][r1]&f[k+1][j][r2];
                    }
                    for (q=1;q<=G;q++) 
                    {
                        r1=zt[3][q][0];r2=zt[3][q][1];  //两个可以转移的字母 
                        if (!f[i][j][3]) f[i][j][3]=f[i][k][r1]&f[k+1][j][r2];
                    }
                }
        if (f[0][l-1][0]) printf("W"),flag=1;
        if (f[0][l-1][1]) printf("I"),flag=1;
        if (f[0][l-1][2]) printf("N"),flag=1;
        if (f[0][l-1][3]) printf("G"),flag=1;
        if (!flag) printf("The name is wrong!");
    }
    
    int main()
    {
        memset(f,0,sizeof(f));
        scanf("%d%d%d%d",&W,&I,&N,&G);
        for (int i=1;i<=W;i++){scanf("%s",&w);cl(0,i);} 
        for (int i=1;i<=I;i++){scanf("%s",&w);cl(1,i);} 
        for (int i=1;i<=N;i++){scanf("%s",&w);cl(2,i);} 
        for (int i=1;i<=G;i++){scanf("%s",&w);cl(3,i);} 
        scanf("%s",&s);
        doit();
        return 0;
    } 
  • 相关阅读:
    Chrome快捷键统计
    数据封装
    数据抽象
    linux c++ 服务器端开发面试必看书籍(转载)
    闭包和高阶函数
    this,call,apply,bind
    DOM浏览器window对象模型
    jquery滚动条
    xml教程
    多态
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673455.html
Copyright © 2020-2023  润新知