BZOJ 1055

1055: [HAOI2008]玩具取名

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 887   Solved: 518
[ Submit][ Status]

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 IN均能变成WW所以WW又可以缩成I或者N 所以最终答案应该按照“WING”的顺序输出IN 

[数据范围]

100%数据满足Len<=200,W、I、N、G<=16





【题解】

 

1055:

题目大意是 给你一个变形后的串,问你它可能是由哪几个字符变化得来的。

一、
我想的,最后的答案只有四个,所以或许可以一个一个试出来。

那么得到目标的字符串,需要 len-1 次变化。
	
分治思想:

I   I    I    I
 \ /      \ /
 W     W
    \   /
    I(N)

dfs(n) =(16)* len(n) * { dfs(x) + dfs(n-x) };
 
很明显这是铁定TLE 的,于是我苦思冥想,突然想到加上记忆化怎么样。
如果加上记忆化 状态数 最多是 len*len*4 中,加上每种状态 的 16 次枚举哪一个变化,得 O( n*n*64 )的时间复杂度,就可以过了。
 
#include<cstdio>
#include<cstring>
#include<cstdlib>

int a[26],n[4],f[4][210][210],len;
char c[4][18][3],s[210];

void dfs(int x,int L,int R)
{
	if(f[x][L][R]!=(-1))return;
	if(L==R)
	{
		f[x][L][R]=(x==a[s[L]-'A']);
		return;
	}
	for(int i=1;i<=n[x];i++)
	{
		for(int j=L;j<R;j++)
		{
			if(j==L && s[L]!=c[x][i][1])continue;
			if((j+1)==R && s[R]!=c[x][i][2])continue;
			
			if(!f[a[c[x][i][1]-'A']][L][j])continue;
			if(!f[a[c[x][i][2]-'A']][j+1][R])continue;
			
			if(f[a[c[x][i][1]-'A']][L][j]==(-1))dfs(a[c[x][i][1]-'A'],L,j);
			if(!f[a[c[x][i][1]-'A']][L][j])continue;
			
			if(f[a[c[x][i][2]-'A']][j+1][R]==(-1))dfs(a[c[x][i][2]-'A'],j+1,R);
			
			if(f[a[c[x][i][2]-'A']][j+1][R]==1 && f[a[c[x][i][1]-'A']][L][j]==1)
			{
				f[x][L][R]=1; break;
			}
		}
		if(f[x][L][R]!=(-1))break;
	}
	if(f[x][L][R]==(-1))f[x][L][R]=0;
}
int main()
{
	scanf("%d%d%d%d",&n[0],&n[1],&n[2],&n[3]);
	memset(f,-1,sizeof(f));
	a['W'-'A']=0; a['I'-'A']=1;
	a['N'-'A']=2; a['G'-'A']=3;
	for(int i=1;i<=n[0];i++)scanf("%s",c[0][i]+1);
	for(int i=1;i<=n[1];i++)scanf("%s",c[1][i]+1);
	for(int i=1;i<=n[2];i++)scanf("%s",c[2][i]+1);
	for(int i=1;i<=n[3];i++)scanf("%s",c[3][i]+1);
	scanf("%s",s+1);
	len=strlen(s+1);
	int key=0;
	for(int i=0;i<4;i++)
	{
		dfs(i,1,len);
		if(f[i][1][len]==1)
		{
			switch (i)
			{
				case 0:printf("W"); break;
				case 1:printf("I"); break;
				case 2:printf("N"); break;
				case 3:printf("G"); break;
			}
			key=1;
		}
	}
	if(!key)printf("The name is wrong!");
	printf("\n");  return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值