玩具取名题解

目录

原题:

Time Limit: 1s    Memory Limit: 128MB

Description

Input

Output

Sample Input

Sample Output

HINT

数据范围

题目大意:

主要思路:

注意事项:

代码(有注释):


原题:

Time Limit: 1s    Memory Limit: 128MB

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

I,N均能变成WW所以WW又可以缩成I或者N所以最终答案应该按照“WING”的顺序输出IN

数据范围

100\%数据满足Len\le 200WING\le 16

题目大意:

给你一个长度为Len的字符串,让你求它最终可以缩成什么字母。

主要思路:

我们可以用区间dp来做,dp[i][j][ch] 表示从区间[i,j]可以合成一个字母ch(ch是整数,W是1,I是2,N是3,G是4),还要用一个vis[i][j][ch],表示i,j两个字母可以合成一个字母ch(都是整数),用区间dp模板轻松搞定。

注意事项:

  1. 边界设置问题
  2. dp的初始化

代码(有注释):

#include<bits/stdc++.h>
using namespace std;
unordered_map<int,char> w;
unordered_map<char,int> mp;//转换 
bool vis[10][10][10];
int a[10];
string s;
bool dp[210][210][10];
int main()
{
	mp['W'] = 1;
	mp['I'] = 2;
	mp['N'] = 3;
	mp['G'] = 4;
	w[1] = 'W';
	w[2] = 'I';
	w[3] = 'N';
	w[4] = 'G';//转换 
	for(int i=1;i<=4;i++)
	{
		cin>>a[i];//输入进来 
	}
	for(int i=1;i<=4;i++)
	{
		for(int j=1;j<=a[i];j++)
		{
			char c1,c2;
			cin>>c1>>c2;
			vis[mp[c1]][mp[c2]][i] = 1;//用两个合成一个标记 
		}
	}
	cin>>s;
	int n=s.size();
	for(int i=1;i<=n;i++)
	{
		dp[i][i][mp[s[i-1]]] = 1;//一个字符肯定可以由这个字符合成的
	}
	for(int len=2;len<=n;len++)
	{
		for(int l=1;l+len-1<=n;l++)
		{
			int r=l+len-1;//基本区间dp模板 
			for(int k=l;k<=r;k++)//枚举断点 
			{
				for(int c1=1;c1<=4;c1++)
				{
					for(int c2=1;c2<=4;c2++)
					{
						for(int c3=1;c3<=4;c3++)//枚举三个字符 
						{
							if(dp[l][k][c2]&&dp[k+1][r][c3]&&vis[c2][c3][c1])//如果区间l~k可以合成c2,k+1~r可以合成c3,c2和c3可以合成c1,那么l~r就可以合成c1。 
							{
								dp[l][r][c1]=1;//标记起来 
							}
						}
					}
				}
			}
		}
	}
	bool flag=1;
	for(int i=1;i<=4;i++)
	{
		if(dp[1][n][i])//如果可以合成 
		{
			cout<<w[i];//输出 
			flag=0;//去除标记 
		}
	}
	if(flag)//如果标记还存在 
	{
		cout<<"The name is wrong!";//就输出错误 
	}
    return 0; 
}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值