【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]
posted @ 2015-04-17 12:14  Tunix  阅读(237)  评论(0编辑  收藏  举报