zoukankan      html  css  js  c++  java
  • 【BZOJ】【1055】【HAOI2008】玩具取名

    区间DP/记忆化搜索


      sigh……看了提示才想到是区间DP >_>我果然还是太弱

      f[l][r][k]表示L到R这段区间能否合并成K,那么就是枚举拆分方案(从哪里断开)和组合方式(左半合成的子母+右半合成的子母 可以合成 K)了……

      记忆化搜索即可= =

     1 /**************************************************************
     2     Problem: 1055
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:1040 ms
     7     Memory:2136 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 1055
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 using namespace std;
    22 inline int getint(){
    23     int v=0,sign=1; char ch=getchar();
    24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    26     return v*sign;
    27 }
    28 const int N=210,INF=~0u>>2;
    29 typedef long long LL;
    30 /******************tamplate*********************/
    31 inline int id(char ch){
    32     if (ch=='W') return 1;
    33     if (ch=='I') return 2;
    34     if (ch=='N') return 3;
    35     if (ch=='G') return 4;
    36 }
    37 char s[N];
    38 int f[N][N][5],a[N],n,num[5];
    39 vector<int>G[5];
    40 bool dfs(int l,int r,int k){
    41     if (f[l][r][k]!=-1) return f[l][r][k];
    42     if (l==r) return f[l][r][k]=a[l]==k;
    43     rep(i,G[k].size()){
    44         int t1=G[k][i]/10,t2=G[k][i]%10;
    45         F(j,l,r-1)
    46             if (dfs(l,j,t1) && dfs(j+1,r,t2)) return f[l][r][k]=1;
    47     }
    48     return f[l][r][k]=0;
    49 }
    50 int main(){
    51 #ifndef ONLINE_JUDGE
    52     freopen("1055.in","r",stdin);
    53     freopen("1055.out","w",stdout);
    54 #endif
    55     memset(f,-1,sizeof f);
    56     F(i,1,4) num[i]=getint();
    57     F(i,1,4) F(j,1,num[i]){
    58         char s[4];
    59         scanf("%s",s);
    60         int x=id(s[0])*10+id(s[1]);
    61         G[i].pb(x);
    62     }
    63     scanf("%s",s);
    64     n=strlen(s);
    65     F(i,1,n) a[i]=id(s[i-1]);
    66     bool sign=0;
    67     if (dfs(1,n,1)) {printf("W"); sign=1;}
    68     if (dfs(1,n,2)) {printf("I"); sign=1;}
    69     if (dfs(1,n,3)) {printf("N"); sign=1;}
    70     if (dfs(1,n,4)) {printf("G"); sign=1;}
    71     if (!sign) printf("The name is wrong!");
    72     return 0;
    73 }
    View Code

    1055: [HAOI2008]玩具取名

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 960  Solved: 566
    [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

    [数据范围]

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


    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    Git:常用命令记录
    JS笔记(二):隐式转换
    vertical-align/line-height:水平垂直居中
    JS笔记(一):声明提升
    Array.prototype.sort():从一道面试题说起
    CSS笔记(一):选择器规范
    FreeCodeCamp:Profile Lookup
    tile_images_offset的简单使用
    vs2013快捷键等(转)
    Qt状态栏的使用(转)
  • 原文地址:https://www.cnblogs.com/Tunix/p/4434506.html
Copyright © 2011-2022 走看看