【BZOJ1055】【HAOI2008】【洛谷P4290】玩具取名

博客介绍了一道区间DP入门题,某人用WING字母命名玩具,可将字母用两个字母替代来扩充名字。题面给出输入输出格式及样例,题解将字母离散化,用二维数组存变形结果,维护三维数组判断字串能否由字母变形而来,还给出了C++代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分类:区间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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值