ZeroJudge D671: Digital Fortress

同題:UVa 11716 – Digital Fortress

上一屆的 IIUPC 有一題「達文西密碼」是以丹布朗的暢銷書「達文西密碼」為故事背景。這一題則是以科技驚悚小說「數位堡壘」為背景。題目給你一個密文,你要用下述的解碼方式來解碼。

比如說,如果密文如下:
WECGEWHYAAIORTNU
輸出則是:
WEAREWATCHINGYOU

上例中所給的密文「WECGEWHYAAIORTNU」有 16 個字元,也就是 4 的平方。請把這些字元以「列優先」(row major,第一列放滿後再放第二列,再第三列……) 的方式置入一個 N*N (本例為 4*4) 的格子。本例密文放置完成後的格子如下:
W E C G
E W H Y
A A I O
R T N U

當我們以「行優先」(column major,取完第一行再取第二行,然後第三行) 的方式將上面格子的字元取出便可以得到以下的明文:
「WEAREWATCHINGYOU」

範例測資

範例輸入範例輸出
輸入的第一行有一個數字 T,接著有 T 筆測資,每筆測資一行,該行便是要處理的密文。密文僅包含大寫字母及空白。密文的總字元數不會超過 10,000。相對於每筆測資,請將明文輸出於一行。若輸入的字元數不是完全平方數,請輸出「INVALID」。
3
WECGEWHYAAIORTNU
DAVINCICODE
DTFRIAOEGLRSI TS
WEAREWATCHINGYOU
INVALID
DIGITAL FORTRESS

解題思路

測資中會有包含空白字元的字串,所以在收完 T 之後要使用 cin.ignore() 才能使用 getline。

可以先判斷字串的長度是否為完全平方數,如果 pow(sqrt(字串長度), 2),也就是字串長度根號的平方,為字串長度的話,就代表字串長度為完全平方數。

可以宣告一個 Vector<string> 來存處理後的字串,並且宣告一個變數 square 為字串長度的根號。跑兩層 square 的 For迴圈,並且預設一個 count 變數為 0,每次將 字串[count] 加到一個暫存字串,並且將 count++,每當內層 For迴圈 結束時就將暫存字串 Push_Back 到 Vector<string> 中。

輸出時一樣要跑兩層 square 的 For迴圈,這邊簡稱第一層為 j 迴圈,第二層為 k 迴圈,每次在 k 迴圈中輸出 Vector<string> 的 [k][j]。第一層迴圈結束之後換行就結束了。

範例程式碼-ZeroJudge D671: Digital Fortress

#include <iostream>
#include <math.h>
#include <vector>
using namespace std;

int main() {
    cin.sync_with_stdio(0);
    cin.tie(0);
    int N;
    cin >> N;
    cin.ignore();
    for (int i = 0; i<N; i++) {
        string str;
        getline(cin, str);
        const int len = int(str.length()), square = int(sqrt(len));
        if (pow(square, 2) != len) {
            cout << "INVALID\n";
            continue;
        }
        vector<string>v;
        int count = 0;
        for (int j = 0; j<square; j++) {
            string tmp = "";
            for (int k = 0; k<square; k++) {
                tmp += str[count];
                count++;
            }
            v.push_back(tmp);
        }
        for (int j = 0; j<square; j++) {
            for(int k = 0; k<square; k++) cout << v[k][j];
        }
        cout << "\n";
    }
}

//ZeroJudge D671
//Dr. SeanXD

發佈留言