zoukankan      html  css  js  c++  java
  • BZOJ 1055: [HAOI2008]玩具取名 記憶化搜索

    題目:

    1055: [HAOI2008]玩具取名

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 409  Solved: 255
    [Submit][Status][Discuss]

    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

    [数据范围]
    30%数据满足Len<=20,W、I、N、G<=6 
    100%数据满足Len<=200,W、I、N、G<=16

    Source

     
    [Submit][Status][Discuss]


    HOME Back


    分析:
    dp[i][j][k]表示從i到j是否可以由第k個字符轉化來
    用記憶化搜索做的話,邊界條件比較好控制些~~

    搜索函數dfs(L,r)
    我們可以枚舉中間分界點i,通過判斷區間[L,i]轉化為字符j,區間[i+1,r]
    轉化的字符k,判斷字符jk是否可以轉化為一個字符

    /*
    
    題目:
        某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一
        个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个
        字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。 现
        在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
    
    分析:
        dp[i][j][k]表示從i到j是否可以由第k個字符轉化來
        用記憶化搜索做的話,邊界條件比較好控制些~~
    
        搜索函數dfs(L,r)
        我們可以枚舉中間分界點i,通過判斷區間[L,i]轉化為字符j,區間[i+1,r]
        轉化的字符k,判斷字符jk是否可以轉化為一個字符
    
    */
    #include <set>
    #include <map>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    
    #define lx(x) (x<<1)
    #define rx(x) (x<<1|1)
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    #define RD(n) scanf("%d",&n)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
    
    /******** program ********************/
    
    const int MAXN = 202;
    
    int dp[MAXN][MAXN][4];
    int num[4],n;
    char s[402];
    int a[405];
    map<char,int> id;
    vector<int> vec[4][4];
    
    void dfs(int l,int r){
        if(dp[l][r][0]!=-1)
            return;
    
        int x = a[l] , y = a[r];
    
        if(l+1==r){
            foreach(i,vec[x][y])
                dp[l][r][ vec[x][y][i] ] = true;
            rep(i,4)
                if(dp[l][r][i]==-1)
                    dp[l][r][i] = 0;
            return;
        }
    
         // 判斷區間[l,i]轉化為字符j,是否可以與區間[i+1,r]轉化的字符由一個字符轉化而來
        for(int i=l;i<r;i++){
            dfs(l,i);
            rep(j,4)
                if(dp[l][i][j]==1){
                    dfs(i+1,r);
                    rep(k,4)
                        if(dp[i+1][r][k]==1)
                            foreach(q,vec[j][k])
                                dp[l][r][vec[j][k][q]] = true;
                }
        }
    
        rep(i,4)
            if(dp[l][r][i]==-1)
                dp[l][r][i] = 0;
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    	//freopen("sum.out","w",stdout);
    #endif
    
        id['W'] = 0;
        id['I'] = 1;
        id['N'] = 2;
        id['G'] = 3;
        rep(i,4)
            RD(num[i]);
    
        rep(i,4)
            rep(j,num[i]){
                scanf("%s",s);
                vec[ id[ s[0] ] ][ id[ s[1] ] ].pb(i);
            }
    
        scanf("%s",s+1);
        n = strlen(s+1);
    
        memset(dp,-1,sizeof(dp));
        rep1(i,n){
            a[i] = id[s[i]];
            dp[i][i][a[i]] = 1;
        }
    
        dfs(1,n);
    
        bool ok = false;
    
        s[0] = 'W';
        s[1] = 'I';
        s[2] = 'N';
        s[3] = 'G';
        for(int i=0;i<4;i++)
            if(dp[1][n][i]){
                ok = true;
                printf("%c",s[i]);
            }
        if(!ok)
            puts("The name is wrong!");
        else
            puts("");
    	return 0;
    }
    

      

  • 相关阅读:
    python基础三大器之装饰器
    python基础之推导式及匿名函数和高阶函数
    python基础之三大器中迭代器和生成器
    python基础之函数(动态参数,注释,名称空间,第一类对象及使用和函数嵌套)
    python基础之初识函数
    python基础之文件操作
    python基础之集合及基础补充(循坏删除,二次编码)
    Python基础之小数据池及深浅拷贝
    python基础之字典
    数据结构-栈
  • 原文地址:https://www.cnblogs.com/yejinru/p/3015216.html
Copyright © 2011-2022 走看看