某 人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个字母用 “WING”中任意两个字母代替,使得自己的名字能够扩充得很长。现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
标签:
某 人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个字母用 “WING”中任意两个字母代替,使得自己的名字能够扩充得很长。现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
第 一行四个整数W、I、N、G。表示每一个字母能由几种两个字母所替代。接下来W行,每行两个字母,表示W可以用这两个字母替代。接下来I行,每行两个字 母,表示I可以用这两个字母替代。接下来N行,每行两个字母,表示N可以用这两个字母替代。接下来G行,每行两个字母,表示G可以用这两个字母替代。最后 一行一个长度不超过Len的字符串。表示这个玩具的名字。
一行字符串,该名字可能由哪些字母变形而得到。(按照WING的顺序输出)如果给的名字不能由任何一个字母变形而得到则输出“The name is wrong!”
W可以变成II所以IIII可以缩成WW IN均能变成WW所以WW又可以缩成I或者N 所以最终答案应该按照“WING”的顺序输出IN
[数据范围]
100%数据满足Len<=200,W、I、N、G<=16
【思路】
区间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 }
bzoj 1055 [HAOI2008]玩具取名(区间DP)
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/5099941.html