• bzoj 1055 [HAOI2008]玩具取名(区间DP)


    1055: [HAOI2008]玩具取名

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

    【思路】

           区间DP。

           设f[l][r][x]表示lr区间的字符是否可以合并为字符x,则有转移方程式:

           f[l][r][x]=f[l][j][p1]&&f[j+1][r][p2],l <= j < r

           其中p1 p2表示x可以差分成的两个字符。

          

           ps:没错我就是在水题 _(:з」∠)_

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
     4 using namespace std;
     5 
     6 const int maxn = 200+10;
     7 int d[maxn][maxn][30];
     8 char s[]="WING";
     9 int h[255];
    10 
    11 char a[4][maxn][3],expr[maxn];
    12 int num[4],n;
    13 
    14 int dp(int l,int r,int x) {
    15     if(l==r) return expr[l]==s[x];
    16     int &ans=d[l][r][x];
    17     if(ans>=0) return ans;
    18     FOR(i,0,num[x]) FOR(j,l,r)
    19         if(dp(l,j,h[a[x][i][0]]) && dp(j+1,r,h[a[x][i][1]])) return ans=1;
    20     return ans=0;
    21 }
    22 
    23 int main() {
    24     memset(d,-1,sizeof(d));
    25     h['W']=0 , h['I']=1 , h['N']=2 , h['G']=3;
    26     FOR(i,0,4) scanf("%d",&num[i]);
    27     FOR(i,0,4) FOR(j,0,num[i])
    28         scanf("%s",a[i][j]);
    29     scanf("%s",expr);
    30     int n=strlen(expr) , flag=0;
    31     FOR(i,0,4)  if(dp(0,n-1,i)) 
    32         flag=1 , printf("%c",s[i]);
    33     if(!flag) puts("The name is wrong!");
    34     return 0;
    35 }
  • 相关阅读:
    Uploader 文件上传
    filters过滤器的使用
    Calendar中遇到的问题
    中科院之旅
    Python基础教程:列表推导式详解
    不会也要知道的,Python四种实现排序的方法
    2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案
    2021字节跳动校招秋招算法面试真题解题报告--leetcode206 反转链表,内含7种语言答案
    求协方差
    国外卡组织的 交换费-interchangefee(发卡行服务费) 和 银联对比
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5099941.html
Copyright © 2020-2023  润新知