HDU 4119 Isabella‘s Message

Problem Description

Isabella and Steve are very good friends, and they often write letters to each other. They exchange funny experiences, talk about people around, share their feelings and write about almost everything through the letters. When the letters are delivered, they are quite afraid that some other people(maybe their parents) would peek. So they encrypted the letter, and only they know how to decrypt it. This guarantees their privacy.
The encrypted message is an N * N matrix, and each grid contains a character.
Steve uses a special mask to work as a key. The mask is N * N(where N is an even number) matrix with N*N/4 holes of size 1 * 1 on it.
The decrypt process consist of the following steps:
1. Put the mask on the encrypted message matrix
2. Write down the characters you can see through the holes, from top to down, then from left to right.
3. Rotate the mask by 90 degrees clockwise.
4. Go to step 2, unless you have wrote down all the N*N characters in the message matrix.
5. Erase all the redundant white spaces in the message.
For example, you got a message shown in figure 1, and you have a mask looks like figure 2. The decryption process is shown in figure 3, and finally you may get a message "good morning".


You can assume that the mask is always carefully chosen that each character in the encrypted message will appear exactly once during decryption.
However, in the first step of decryption, there are several ways to put the mask on the message matrix, because the mask can be rotated (but not flipped). So you may get different results such as "od morning go" (as showed in figure 4), and you may also get other messages like "orning good m", "ng good morni".


Steve didn't know which direction of the mask should be chosen at the beginning, but after he tried all possibilities, he found that the message "good morning" is the only one he wanted because he couldn't recognize some words in the other messages. So he will always consider the message he can understand the correct one. Whether he can understand a message depends whether he knows all the words in the message. If there are more than one ways to decrypt the message into an understandable one, he will choose the lexicographically smallest one. The way to compare two messages is to compare the words of two messages one by one, and the first pair of different words in the two messages will determine the lexicographic order of them.
Isabella sends letters to Steve almost every day. As decrypting Isabella's message takes a lot of time, and Steve can wait no longer to know the content of the message, he asked you for help. Now you are given the message he received, the mask, and the list of words he already knew, can you write a program to help him decrypt it?

 

Input

The first line contains an integer T(1 <= T <= 100), indicating the number of test cases.
Each test case contains several lines.
The first line contains an even integer N(2 <= N <= 50), indicating the size of the matrix.
The following N lines each contains exactly N characters, reresenting the message matrix. The message only contains lowercase letters and periods('.'), where periods represent the white spaces.
You can assume the matrix contains at least one letter.
The followingN lines each containsN characters, representing the mask matrix. The asterisk('*') represents a hole, and period('.') otherwise. The next line contains an integer M(1 <= M <= 100), the number of words he knew.
Then the following M lines each contains a string represents a word. The words only contain lowercase letters, and its length will not exceed 20.

 

Output

For each test case in the input, print one line: "Case #X: Y", where X is the test case number (starting with 1) and Y is Isabella's message.
If Steve cannot understand the message, just print the Y as "FAIL TO DECRYPT".

 

Sample Input

 
 

3 4 o.do .ng. grmn o.i. .*.. *.*. .... *... 2 good morning 4 ..lf eoyv oeou vrer ..*. .*.. .... *.*. 5 i you the love forever 4 .sle s.c. e.fs ..uu *... .*.. ...* ..*. 1 successful

 

Sample Output

 
 

Case #1: good morning Case #2: love you forever Case #3: FAIL TO DECRYPT

思路:题目会给出史蒂夫所认识的所有单词,因此只要将解码后得出的单词在认识的单词中进行查找即可,有可能有多组答案,因此可以用set存储答案,直接输出第一组单词就是字典序最小的答案;

        为了方便查找我采用set存储所有认识的单词;因为蒙版旋转的方向是固定的,因此单词组合最多有四种情况(即:{0,1,2,3},{1,2,3,0},{2,3,0,1},{3,0,1,2}),枚举四种情况检查是否符合答案;

AC代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
using namespace std;

const int N=55;

int n,m;
char mp[N][N],g[N][N];
string s[4],ch[110];
set<string> st,res;
int seq[][4]={{0,1,2,3},{1,2,3,0},{2,3,0,1},{3,0,1,2}};//组合方式

void filp()//旋转蒙版
{
	char tmp[N][N];
	memcpy(tmp,g,sizeof g);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			g[j][n-i-1]=tmp[i][j];
}

void deal() //读取字符串
{
	for(int i=0;i<4;i++)
		s[i]="";
	
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<n;j++)
			for(int k=0;k<n;k++)
				if(g[j][k]=='*')
					s[i]+=mp[j][k]!='.'?mp[j][k]:' ';
		filp();
	}
}

void check(int u)//检查是否合法
{
	string str="",tmp="";
	string x="";
	for(int i=0;i<4;i++)
		tmp+=s[seq[u][i]];
	int i=0;
	while(tmp[i]==' ')
		i++;
	
	bool f=1;
	for(;i<tmp.size();i++)
	{
		if(tmp[i]==' ')
			f=0;
		else
		{
			if(!f)
			{
				str+=' ';
				f=1;
			}
			str+=tmp[i];
		}
	}
	
	for(int i=0;i<str.size();i++)
	{
		if(str[i]==' '&&x.size())
		{
			if(st.find(x)==st.end())
				return;
			x="";
		}
		else
			x+=str[i];
	}
	if(st.find(x)==st.end())
		return;
	
	res.insert(str);
}

int main()
{
	int t;
	scanf("%d",&t);
	for(int k=1;k<=t;k++)
	{
		st.clear();
		res.clear();
		
		scanf("%d",&n);
		for(int i=0;i<n;i++)
			scanf("%s",mp[i]);
		for(int i=0;i<n;i++)
			scanf("%s",g[i]);
		
		scanf("%d",&m);
		for(int i=0;i<m;i++)
		{
			cin>>ch[i];
			st.insert(ch[i]);
		}	
		
		deal();
		
		for(int i=0;i<4;i++)
			check(i);
		if(res.size())
		{
			printf("Case #%d: ",k);
			cout<<*res.begin()<<endl;
		}	
		else
			printf("Case #%d: FAIL TO DECRYPT\n",k);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Double.Qing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值