ZeroJudge B683: 環形偵測

為了做研究,源外老教授弄到了一台特殊的 DNA 掃描儀,這台機器可以把目前獲得的 DNA 們分離成一個個的小片段,之後拍張照片作為掃描結果,拿來分析與研究。

掃描結果會是高度為 H、寬度為 W 的矩形方格,每個方格可能有兩種狀態:「有 DNA」或「無 DNA」。在所獲得的結果中,如果兩個上、下、左,右相鄰的方格都滿足「有 DNA」,那麼稱作這兩格的 DNA 為聯通的。所有直接或間接聯通,且滿足「有DNA」的方格,則屬於同一個片段。如果兩個「有 DNA」的方格完全沒有連通,則屬於不同片段。換句話說,片段由許多直接或間接連通而「有 DNA」的一些方格所組成。

已知每個片段的長相只有「線形」與「環形」兩種可能。

「線形」的片段為一條鏈,也即可以在此片段中找到恰好一個起始方格,接著沿著唯一的方向,依序找尋下一個方格,直到遇到最後一個方格為止,且此方格與起始方格不會上、下、左,右相臨。保證在找尋方格的過程中不會遇到任何岔路,且此片段至少包含 2 格。

「環形」的片段為一個環,也即在此片段中,每個方格都可以視為起始方格,從起始方格出發,從恰兩個方向中任選一個前進,接著沿著唯一的方向,依序找尋下一個方格,直到遇到最後一個方格為止,此方格會與起始方格上、下、左,右相臨。保證在找尋方格的過程中不會遇到岔路,從起始方格出發必定恰有兩個可能的找尋方向,且此片段至少包含 8 格

在這次的研究中,源外老頭不關心任何「線形」的片段,但想要好好分析「環形」的片段,由於這些資料太過於龐大了,你希望寫一支程式協助分析這些結果。

範例測資

範例輸入範例輸出
輸入的第一列為兩個正整數 H 和 W,表示掃描結果為高度 H、寬度 W 的矩形方格。
接著共有 H 列,每列均恰有 W 個字元,其中字元「.」(不含引號)表示該格「有 DNA」,字元「#」(不含引號)表示該格「無 DNA」。除此之外,該列不會有其他的字元。
請輸出一列,其中包含三個正整數 X、Y、Z,並以一個空白隔開,表示總共有 X 個「環形」片段,這些片段長度的總和為 Y,乘積為 Z。保證至少有一個「環形」片段,且滿足 Z < 264
3 3

.#.
1 8 8
5 6
######
…#..
.#.###
…#.#
####.#
1 8 8
11 7
…….
.#####.
.#…#.
.#.#.#.
.#…#.
.#####.
…….
#######
#….#.
..##.#.
.###…
2 32 192

解題思路

使用 DFS,每次從主程式呼叫 DFS 的時候紀錄目前的陣列位置,當 DFS 走回起點的時後判斷走的步數是否 >= 4,如果 >= 4 的話就代表走了一圈,將走的步數存到一個陣列中。走 DFS 的時候優先判斷是否可以往下或右走,只要走了一步就 break 迴圈。

將答案陣列的長度輸出設定為 X,陣列中資料總和設定為 Y,陣列中所有資料的乘積設定為 Z。另外,因為乘積會很大所以需要使用 Unsigned Long Long Int

範例程式碼-ZeroJudge B683: 環形偵測

#include <iostream>
#include <vector>
#include <map>
using namespace std;

int H, W, loc[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
vector<string>num;
vector<unsigned long long int>ans;
map<pair<int, int>, int>MAP;

pair<int, int> axis (int a, int b)
{
    pair<int, int>tmp;
    tmp.first = a;
    tmp.second = b;
    return tmp;
}

void DFS(pair<int, int>point, pair<int, int>start, unsigned long long int count)
{
    MAP[point]++;
    if (point == start && MAP[point] == 1 && count >= 4)
    {
        ans.push_back(count);
        return;
    }
    for (int i = 0; i<4; i++)
    {
        int yy = point.first + loc[i][0], xx = point.second + loc[i][1];
        if (yy >= 0 && yy < H && xx >= 0 && xx < W && num[yy][xx] == '.' && MAP[axis(yy, xx)] == 0)
        {
            DFS(axis(yy, xx), start, count+1);
            return;
        }
    }
}

int main() {
    cin.sync_with_stdio(0);
    cin.tie(0);
    cin >> H >> W;
    for (int i = 0; i<H; i++)
    {
        string str;
        cin >> str;
        num.push_back(str);
    }
    for (int i = 0; i<H; i++)
    {
        for (int j = 0; j<W; j++)
        {
            if (MAP[axis(i, j)] == 0 && num[i][j] == '.')
            {
                MAP[axis(i, j)]--;
                DFS(axis(i, j), axis(i, j), 0);
            }
        }
    }
    cout << ans.size();
    unsigned long long int Y = 0, Z = 1;
    for (int i = 0; i<ans.size(); i++)
    {
        Y += ans[i];
        Z *= ans[i];
    }
    cout << " " << Y << " " << Z << "\n";
}

//ZeroJudge B683
//Dr. SeanXD

發佈留言