BZOJ 1055 区间DP

1055: [HAOI2008]玩具取名

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

 
题解:暴力区间DP
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
#define maxn 201
vector<int > mp[maxn];
int a,b,c,d,sum;
char ch[3],s[201];
int dp[201][201][101];
char next[400];
int str[555];
void stt(char a[])
{
    sum=0;
    if(a[0]=='W')
    {
        sum+=1;
    }else if(a[0]=='I')sum+=2;else if(a[0]=='N')sum+=3;else if(a[0]='G')sum+=4;
    sum*=10;
        if(a[1]=='W')
    {
        sum+=1;
    }else if(a[1]=='I')sum+=2;else if(a[1]=='N')sum+=3;else if(a[1]='G')sum+=4;
}
int  main()
{

   next[1]='W';str['W']=1;
   next[2]='I';str['I']=2;
   next[3]='N';str['N']=3;
   next[4]='G';str['G']=4;
     scanf("%d%d%d%d",&a,&b,&c,&d);
     for(int i=1;i<=a;i++)
     {
         scanf("%s",ch);
         stt(ch);
         //cout<<sum<<endl;
         mp[sum].push_back(1);
     }
     for(int i=1;i<=b;i++)
     {
         scanf("%s",ch);
         stt(ch);
         mp[sum].push_back(2);
     }
      for(int i=1;i<=c;i++)
     {
         scanf("%s",ch);
         stt(ch);
        mp[sum].push_back(3);
     }
      for(int i=1;i<=d;i++)
     {
         scanf("%s",ch);
         stt(ch);
         mp[sum].push_back(4);
     }
     scanf("%s",s);
     memset(dp,0,sizeof(dp));
     for(int i=0;i<strlen(s);i++){
        dp[i][i][str[s[i]]]=1;
     }
     int n=strlen(s);
    for(int l=2;l<=n;l++)
    {
        for(int i=0;i<n-l+1;i++)
        {
            for(int k=i;k<i+l-1;k++)
            {
                for(int j=1;j<=4;j++)
                    for(int h=1;h<=4;h++)
                {
                    if(dp[i][k][j]&&dp[k+1][i+l-1][h])
                    {
                        for(int f=0;f<mp[j*10+h].size();f++)
                        {
                            dp[i][i+l-1][mp[j*10+h][f]]=1;
                        }
                    }
                }
            }
        }
    }
    int flag=0;
    for(int i=1;i<=4;i++)
        if(dp[0][n-1][i])cout<<next[i],flag=1;
        if(!flag)cout<<"The name is wrong!";
    cout<<endl;
    return 0;
}
代码君

 

posted @ 2015-09-10 14:45  meekyan  阅读(256)  评论(0编辑  收藏  举报