Isabella's Message HDU - 4119 (模拟)

题目描述:给定一个n*n的messag图,由字母和空格组成,用一个n*n有n*n/4个洞的mask盖在messa上面,通过洞自上至下,从左到右读取洞中露出的字母或空格,然后将mask顺时针旋转九十度继续读取,直到转了360度,这4次读取的信息可以组成若干单词(单词间通过空格间隔),若出现的所有单词都在给定的单词之内,则为有效情况。由于第一次将空洞摆放时的方式不同,故可能有多种读取结果。若有若干结果符合要求,则输出字典序最小的一组。

思路:直接模拟即可。不过要注意不仅要处理前后多余的空格,单词与单词之间的空格也要处理,单词间只能由一个空格间隔,多余空格要舍弃。忘记处理中间空格是我一直PE的原因。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<sstream>
#include<deque>
#include<stack>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 50 + 20;
const int mod = 10000007;
const int dx[] = {1, -1, 0, 0, -1, -1, 1, 1};
const int dy[] = {0, 0, -1, 1, -1, 1, -1, 1};
const int Dis[] = {-1, 1, -5, 5};
const double inf = 0x3f3f3f3f;
int n, m;
char message[maxn][maxn];
char a[maxn][maxn], b[maxn][maxn], c[maxn][maxn], d[maxn][maxn];
map<string, int> mp;
vector<string> ans;
void get_mask(char x[maxn][maxn], char y[maxn][maxn]){//旋转给定的mask图,得到一开始摆放时mask所有的情况。
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            y[i][j] = x[n - 1 - j][i];
        }
    }
}
string get_cover(char x[maxn][maxn]){//读取mask挡住message后露出的信息。
    string cnt = "";
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            if(x[i][j] == '*'){//洞
                if(message[i][j] == '.'){//空格
                    cnt += ' ';
                }
                else{//小写字母
                    cnt += message[i][j];
                }
            }
//            cout << "cnt==" << cnt << endl;
        }
    }
//    cout << "cnt******" << cnt << endl;
    return cnt;
}
void solve(string s1){//读取单词并判断是否符合要求。
    int cur1, cur2;
    bool ok, judge;
    string tmp;
    cur1 = 0; ok = false;judge = true;
    int len = s1.size();
    for(int i = 0; i < len; ++i){
        if(!ok){
            while(s1[cur1] == ' ' && cur1 < len) ++cur1;
            if(cur1 >= len) break;
            ok = true;
            cur2 = cur1;
        }
        if(ok){
            while(s1[cur2] != ' ' && cur2 < len) ++cur2;
            tmp = s1.substr(cur1, cur2 - cur1);
//            cout << "cur1==" << cur1 << " cur2==" << cur2 << " tmp==" << tmp << endl;
            if(!mp.count(tmp)){//读取到的单词不在给定单词中,直接退出。
                judge = false; break;
            }
            else{
                cur1 = cur2;
            }
            ok = false;
        }
    }
    if(judge){//所有单词均符合要求
        cur1 = 0, cur2 = len - 1;
        while(s1[cur1] == ' ' && cur1 < len) ++cur1;//处理最前面的多余空格
        while(s1[cur2] == ' ' && cur2 >= 0) --cur2;//处理最后面的多余空格。
        if(cur1 > cur2 || (cur1 == cur2 && s1[cur1] == ' ')) return;
        tmp = s1.substr(cur1, cur2 - cur1 + 1);
//        cout << "s1+++" << s1 << " tmp+++" << tmp << "***" << endl;
        ans.push_back(tmp);
    }
}
int main(){
//    freopen("in.txt","r", stdin);
//    freopen("out.txt","w", stdout);
    int t;
    int kase = 0;
    scanf("%d", &t);
    while(t--){
        mp.clear(); ans.clear();
        scanf("%d", &n);
        for(int i = 0; i < n; ++i) scanf("%s", message + i);
        for(int i = 0; i < n; ++i) scanf("%s", a + i);//初始mask图
        scanf("%d", &m);
        string word;
        for(int i = 1; i <= m; ++i){
            cin >> word;//给定单词
            mp[word] = i;
        }
        get_mask(a, b);
        get_mask(b, c);
        get_mask(c, d);
        //abcd ---- "  good morning  "//共四种情况,一一模拟出来即可。
        string s1 = "";
        s1 += get_cover(a);
        s1 += get_cover(b);
        s1 += get_cover(c);
        s1 += get_cover(d);
//        cout << "s1==" << s1 << "**" << endl;
        solve(s1);
        //bcda ---- "od morning    go"
        s1 = "";
        s1 += get_cover(b);
        s1 += get_cover(c);
        s1 += get_cover(d);
        s1 += get_cover(a);
//        cout << "s1==" << s1 << "**" << endl;
        solve(s1);
        //cdab ---- "orning    good m"
        s1 = "";
        s1 += get_cover(c);
        s1 += get_cover(d);
        s1 += get_cover(a);
        s1 += get_cover(b);
//        cout << "s1==" << s1 << "**" << endl;
        solve(s1);
        //dabc ---- "ng    good morni"
        s1 = "";
        s1 += get_cover(d);
        s1 += get_cover(a);
        s1 += get_cover(b);
        s1 += get_cover(c);
//        cout << "s1==" << s1 << "**" << endl;
        solve(s1);
        printf("Case #%d: ", ++kase);
        if(ans.empty()){//无解
            printf("FAIL TO DECRYPT\n"); continue;
        }
        else{
            sort(ans.begin(), ans.end());//处理中间空格,即两个单词间只能有一个空格分割它们。
            string answer = "", tmp;
            stringstream ss(ans[0]);
            bool ok = false;
            while(ss >> tmp){
                if(ok) answer += " ";
                else ok = true;
                answer += tmp;

            }
//            cout << "**";
            cout << answer << endl;
//            cout << "**" << endl;
        }

    }
    return 0;
}

/*
3

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

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值