HDU 4119Isabella's Message2011成都現場賽I題(字串模擬)

果7發表於2013-09-03

Isabella's Message

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1377    Accepted Submission(s): 406


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
 

Source
 



題目大意:給一個n*n的矩陣,n為偶數,矩陣由小寫字母和'.'組成,'.'表示空格,再給一個n*n矩陣,由'.'和'*'組成,'*'表示洞,'.'表示障礙。

現在將2張卡片重合,將能看到的字元從上往下從左往右依次取出組成一個新單詞。卡片可以順時針旋轉90度,再取出能看到的

單詞,一共有4個單詞,4個單詞再依次組成一個句子,因為卡片是連續轉動的,所以4個單詞首尾相連,任取一個做句子頭,所

以句子一共也是4個。再給m個單詞,求出字典序最小的句子並要求句子中每個單詞都在給定的m個單詞中。

座標轉換公式(i,j)——> (j,n-i+1) 座標變換公式,從1,1開始。

先求出4個字串連線好形成的字串,然後改變連線順序,組成新的4個字串連線好形成的字串。然後查詢是否全部由單詞本中的單片語成。(這段話來自於Hadis_yuki)


        解題思路:開始是中間的連續的空格沒有處理好,然後還有map沒有初始化,結果WA出翔了。終於A了,當時比賽如果我做的話,可能會一WA到底。。需要修煉啊!


        題目地址:Isabella's Message


AC程式碼:

#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
char a[55][55];     //開始的地圖
char tmp[55][55];
char mes[10005];  //存放連線好以後的字串,還沒有去空格
string res[5];
int visi[55][55]; //表示洞
int vis[55][55];  //visi的temp
int n,w;
map <string,int> word;  //認識的單詞

int cmp(string a,string b)
{
    if(a<b) return 1;
    return 0;
}

void rotat()  //順時針旋轉90度
{
    int i,j;
    memset(vis,0,sizeof(vis));
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
          if(visi[i][j]==1)
            vis[j][n+1-i]=1;
    memset(visi,0,sizeof(visi));
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
           visi[i][j]=vis[i][j];
}

void solve()
{

    int t=0; //如果存在一個滿足條件則變為1
    int i,j,k,l;
    for(i=0;i<=3;i++)
        res[i]="";  //每次都要清空
    for(l=0;l<4;l++)
    {
        int flag=0;
        k=4;
        int p=0;
        while(k--)
        {
           for(i=1;i<=n;i++)
              for(j=1;j<=n;j++)
                if(visi[i][j]==1)
                   mes[p++]=a[i][j];
           rotat();
        }
        mes[p]='\0';  //mes是存放連線好以後的字串,還沒有去空格
        //cout<<mes<<endl;
        i=0;
        while(i<p)  //去前面的空格
        {
            if(mes[i]==' ')
                i++;
            else
                break;
        }

        j=p-1;  //去後面的空格
        while(j>=0)
        {
            if(mes[j]==' ')
                j--;
            else
                break;
        }
        p=j;
        //cout<<i<<" "<<p<<endl;
        //cout<<mes<<endl;
        char tmp1[55];
        int tt=0;
        for(j=i;j<=p;j++)
        {
            if(mes[j]==' '&&mes[j+1]==' ')  //處理中間的空格
                continue;
            else if(mes[j]==' '||j==p)
            {
                if(j==p)
                    tmp1[tt++]=mes[j];
                tmp1[tt]='\0';
                //cout<<tt<<endl;
                tt=0;
                //cout<<tmp1<<endl;
                if(word[tmp1])
                {
                    if(res[t]=="")
                        res[t]=res[t]+tmp1;
                    else
                        res[t]=res[t]+" "+tmp1;
                }
                else
                {
                    res[t]="";
                    flag=1;
                    break;
                }
            }
            else
            {
                tmp1[tt++]=mes[j];
            }
        }

        if(!flag) t++;
        rotat();
    }

    if(t==0)
        puts("FAIL TO DECRYPT");
    else
    {
        sort(res,res+t,cmp);
        cout<<res[0]<<endl;
    }
}

int main()
{
    int tes,i,j;
    scanf("%d",&tes);
    for(int te=1;te<=tes;te++)
    {
        memset(visi,0,sizeof(visi));
        scanf("%d",&n);
        for(i=1;i<=n;i++)
          scanf("%s",a[i]+1);  //a代表地圖
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
              if(a[i][j]=='.')
                 a[i][j]=' ';
        for(i=1;i<=n;i++)
        {
            scanf("%s",tmp[i]+1);
            for(j=1;j<=n;j++)
                if(tmp[i][j]=='*')
                   visi[i][j]=1;   //visi代表*
        }

        scanf("%d",&w); //認識的單詞數
        string temp;
        word.clear();
        for(i=0;i<w;i++)
        {
           cin>>temp;
           word[temp]=2;
        }
        //temp="}";
        //word[temp]=2;
        printf("Case #%d: ",te);
        solve();
    }

    /*int i,w;
    scanf("%d",&w); //認識的單詞數
    string temp;
    for(i=0;i<w;i++)
    {
        cin>>temp;
        word[temp]=2;
    }
    temp="}";
    word[temp]=2;

    char tm[20];
    while(cin>>tm)
    {
        if(word[tm])
            cout<<"yes"<<endl;
        else
            cout<<"no"<<endl;
    }*/

    return 0;
}

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



相關文章