题意:
给出一个表格和一块蒙版, 露出的字母按一定顺序读出, 蒙版旋转, 初始位置不定.
只认识给定的一些词. 问可辨识的短语. 多种情况输出字典序最小的.
思路:
字符串处理的模拟题.
主要是有几步:
1. 读入.
2. 得到蒙版四个方向读出的串.
3. 将这四个串以四种方式串联.
4. 消除前导空格, 合并中间连续的多个空格.
5. 判断是否是认识的词.
6. 将字典序最小的输出.
模拟恶心题, 写清步骤很重要. 磨刀不误砍柴工, 不然后面很容易乱套!
其中, 2 中分出两个函数, 分别收集 和 旋转.
3 中可以用一个矩阵来显示4个循环. 比直接for 要清晰些...
4 是最麻烦的!
仔细分析各个标志改变状态的时间点 和 各个标志发挥作用以及清除的时间点!!!
5 查找直接用set 中的find 函数, 但是要认识到 判断是恰好发生在遇到空格之后,且判断完毕tmp清空 .
#include <set>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
char code[55][55],mark[55][55],s[25];
int t,n,m,nCase = 0;
set<string> dic,ans;
string getstring()
{
string ret("");
for(int i = 0; i < n; ++i)for(int j = 0; j < n; ++j)if(mark[i][j] == '*') ret += code[i][j];///dia-circle + judge
return ret;
}
void rotate()
{
char tmp[55][55];
for(int i = 0; i < n; ++i)for(int j = 0; j < n; ++j)tmp[i][j] = mark[i][j];///copy
for(int i = 0; i < n; ++i)for(int j = 0; j < n; ++j)mark[j][n-1-i] = tmp[i][j];///rotate
}
string preprocess(string s)///deal with blanks
{
string ret("");
int len = s.length();
bool flag = true;///ignore blank
int i = 0;
while(s[i] == '.')i++;
for(; i < len; ++i)
{
if(s[i] == '.')
{
flag = false;///blank delay!!! only mark it when encounter blank, because you may encounter blanks!!!
}//the blank after the first word activated the flag
else//while the second word set the first blank and at the same time eliminated the flag
{
if(!flag)
{
ret += ' ';
flag = true;
}
ret += s[i];
}
}
return ret;
}
bool check(string s)
{
int len = s.length();
string key;
for(int i = 0; i < len; ++i)
{
if(s[i] == ' ')
{
if(dic.find(key) == dic.end()) return false;
key.clear();
}
else key += s[i];
}
if(dic.find(key) == dic.end()) return false;
return true;
}
int r[4][4] =
{
{0,1,2,3},
{1,2,3,0},
{2,3,0,1},
{3,0,1,2}
};//circle shift
void solve()
{
scanf("%d",&n);
dic.clear();
ans.clear();
for(int i = 0; i < n; ++i) scanf("%s",code[i]);
for(int i = 0; i < n; ++i) scanf("%s",mark[i]);
scanf("%d",&m);
for(int i = 0; i < m; ++i)
{
scanf("%s",s);
string d(s);///char to string
dic.insert(d);///set
}
string tostring[4];
for(int i = 0; i < 4; ++i)
{
tostring[i] = getstring();
rotate();
}///get four string
for(int i = 0; i < 4; ++i)
{
string tocheck("");
for(int j = 0; j < 4; ++j) tocheck += tostring[r[i][j]];///concatenate string
string st = preprocess(tocheck);
if(check(st)) ans.insert(st);
}
printf("Case #%d: ",++nCase);
if(ans.size() == 0) printf("FAIL TO DECRYPT\n");
else printf("%s\n",(*ans.begin()).c_str());///automatically lexicographically ordered in set
}
int main()
{
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}