时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
某人有一套玩具,并想法给玩具命名。首先他选择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
输出
IN
题解
题目虽然输入的是字母,但是我们可以当做数字来处理
重要的两个数组,均为bool型
dp[i][j][k]表示区间[i,j]是否是由k转化而来的
can[i][j][k]表示i是否可以用 j k 两个字母代替
can是在读入时更新
我们想一想区间更新的条件:
区间[l,r],中间点为k
z,z1,z2为1~4,表示为WING
如果左区间[l,k+1]可以由z1转化(即代码dp[l][k][z1]),右区间[k+1,r]可以由z2转化(代码dp[k+1][r][z2]),
z可以用z1和z2来代替(代码dp[z][z1][z2]),那是不是就说明区间[l,r]是由z转化的
(相当于z1,z2是一个中转站,用来将区间[l,r]与z联系在一起)
套上区间dp的万能模板
就能得到
for(int i=1;i<=len;i++) dp[i][i][a[i]]=true;//从i到i可以由他自己转化
for(int led=1;led<len;led++)//列举长度的可能性
for(int l=1;l<=len-led;l++)//列举左界的可能性
{
int r=l+led;//右界可以算出来
for(int k=l;k<r;k++) //在左右之间列举可能的断点
for(int z=1;z<=4;z++) //列举l到r(需要的区间)可能转化成的字母
for(int z1=1;z1<=4;z1++) // 列举l到k(借助的左区间)
for(int z2=1;z2<=4;z2++) //列举k + 1到r(借助的右区间)
if(can[z][z1][z2] && dp[l][k][z1] && dp[k+1][r][z2])
//如果z1、z2可以转化成z 并且 l到k可以变成z1 并且k+1到r可以变成z2
dp[l][r][z]=true;
//那么l到r就可以转化成z
}
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e2+7;
int dp[maxn][maxn][maxn];
bool can[maxn][maxn][maxn];
int p[maxn];
char s[maxn];
int a[300];
int change(char i){
if(i=='W') return 1;
if(i=='I') return 2;
if(i=='N') return 3;
if(i=='G') return 4;
}
int main()
{
a['W']=1;
a['I']=2;
a['N']=3;
a['G']=4;
for(int i=1;i<=4;i++)cin>>p[i];
for(int i=1;i<=4;i++)
{
for(int j=1;j<=p[i];j++)
{
char x,y;
cin>>x>>y;
can[i][a[x]][a[y]]=1;
}
}
cin>>(s+1);
int n=strlen(s+1);
// cout<<n<<endl;
for(int i=1;i<=n;i++)dp[i][i][a[s[i]]]=1;
for(int len=2;len<=n;len++)
{
for(int i=1;i<=n;i++)
{
int j=i+len-1;
if(j>n)break;
for(int k=i;k<=j;k++)
{
for(int z=1;z<=4;z++)
{
for(int z1=1;z1<=4;z1++)
{
for(int z2=1;z2<=4;z2++)
{
if(can[z][z1][z2]&&dp[i][k][z1]&&dp[k+1][j][z2])
dp[i][j][z]=1;
}
}
}
}
}
}
bool flag=false;
if(dp[1][n][1]) {
flag=true;printf("W");}
if(dp[1][n][2]) {
flag=true;printf("I");}
if(dp[1][n][3]) {
flag=true;printf("N");}
if(dp[1][n][4]) {
flag=true;printf("G");}
if(!flag) printf("The name is wrong!");
}