分类:区间DP
难度:入门
题面
题目描述
某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。
现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
输入输出格式
输入格式:
第一行四个整数W、I、N、G。表示每一个字母能由几种两个字母所替代。
接下来W行,每行两个字母,表示W可以用这两个字母替代。
接下来I行,每行两个字母,表示I可以用这两个字母替代。
接下来N行,每行两个字母,表示N可以用这两个字母替代。
接下来G行,每行两个字母,表示G可以用这两个字母替代。
最后一行一个长度不超过Len的字符串。表示这个玩具的名字。
输出格式:
一行字符串,该名字可能由哪些字母变形而得到。(按照WING的顺序输出)
如果给的名字不能由任何一个字母变形而得到则输出“The name is wrong!”
输入输出样例
输入样例#1:
1 1 1 1
II
WW
WW
IG
IIII
输出样例#1:
IN
题解
将W,I,N,G分别离散化为数字1~4
二维数组 list[][] 储存题面中给出的字符变形后结果
维护三维数组 f[i][j][k] ,其值表示从下标i到j的字串是否可以有字母k变形而来
- hint:初始化数组f时将 f[i][i][str[i]]标记为1,即字符串本身可以表示本身
代码(C++)
#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 210;
char str[maxn];
int tot = 0;
int list[maxn][3] = {0,};
int f[maxn][maxn][5] = {0,};
int num[5] = {0,};
int len;
int check(char a) {
if(a=='W') return 1;
if(a=='I') return 2;
if(a=='N') return 3;
if(a=='G') return 4;
}
int main()
{
for(int i=1;i<=4;i++) {
scanf("%d",&num[i]);
}
for(int i=1;i<=4;i++) {
for(int j=1;j<=num[i];j++) {
getchar();
char str1;
list[++tot][0] = i;
scanf("%c",&str1);
list[tot][1] = check(str1);
scanf("%c",&str1);
list[tot][2] = check(str1);
}
}
getchar();
scanf("%s",str+1);
len = strlen(str+1);
for(int i=1;i<=len;i++) f[i][i][check(str[i])] = 1;
for(int i=len;i>0;i--) {
for(int j=i+1;j<=len;j++) {
for(int k=i;k<j;k++) {
for(int l=1;l<=tot;l++) {
if(f[i][k][list[l][1]] && f[k+1][j][list[l][2]]) {
f[i][j][list[l][0]] = 1;
}
}
}
}
}
int p = 0;
for(int i=1;i<=4;i++) {
if(f[1][len][i]) {
p = 1;
if(i==1) printf("W");
if(i==2) printf("I");
if(i==3) printf("N");
if(i==4) printf("G");
}
}
if(!p) printf("The name is wrong!");
puts("");
return 0;
}