20241201每日一題洛谷P1683

才瓯發表於2024-12-01

普及-每日一題洛谷P1683

題目描述

不是任何人都可以進入桃花島的,黃藥師最討厭像郭靖一樣呆頭呆腦的人。所以,他在桃花島的唯一入口處修了一條小路,這條小路全部用正方形瓷磚鋪設而成。有的瓷磚可以踩,我們認為是安全的,而有的瓷磚一踩上去就會有噴出要命的毒氣,那你就死翹翹了,我們認為是不安全的。你只能從一塊安全的瓷磚上走到與他相鄰的四塊瓷磚中的任何一個上,但它也必須是安全的才行。

由於你是黃蓉的朋友,她事先告訴你哪些磚是安全的、哪些磚是不安全的,並且她會指引你飛到第一塊磚上(第一塊磚可能在任意安全位置),現在她告訴你進入桃花島的秘密就是:如果你能走過最多的瓷磚並且沒有死,那麼桃花島的大門就會自動開啟了,你就可以從當前位置直接飛進大門了。

注意:瓷磚可以重複走過,但不能重複計數。

輸入格式

第一行兩個正整數 \(W\)\(H\),分別表示小路的寬度和長度。

以下 \(H\) 行為一個 \(H\times W\) 的字元矩陣。每一個字元代表一塊瓷磚。其中,. 代表安全的磚,# 代表不安全的磚,@ 代表第一塊磚。

輸出格式

輸出一行,只包括一個數,即你從第一塊磚開始所能安全走過的最多的磚塊個數(包括第一塊磚)。

樣例輸入

11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........

樣例輸出

59

資料規模與約定

對於全部的測試點,保證 \(1 \leq W,H\le 20\)

DFS搜尋,每次記錄沒有走過的瓷磚數

地圖的讀入,使用%s字串讀入每一行

scanf("%d %d",&w,&h);
for (int i=0;i<h;i++)
    scanf("%s",g[i]);

遍歷地圖找到@起點,開始搜尋

for (int i=0;i<h;i++)
     for (int j=0;j<w;j++)
         if (g[i][j]=='@')
             dfs(i,j);

定義向量,連通四個方向

int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};

DFS搜尋函式

void dfs(int x,int y){
    for (int i=0;i<4;i++){
        int tx=x+dx[i],ty=y+dy[i];
        if (tx<0||tx>=h||ty<0||ty>=w) continue;//超過地圖邊界,該路徑無效
        if (g[tx][ty]!='.') continue;//非'.'不走
        if (st[tx][ty]) continue;//之前走過的路徑不走
        st[tx][ty]=1;
        ans++;
        dfs(tx,ty);
    }
}

每次DFS都遍歷四個可連通的方向,判斷路徑是否合法

st陣列記錄之前走過的路徑,不能走回頭路,回溯會重複經過節點

1 -> 2 ->3 -> 4
         5

當 4 走不通時,直接結束當前狀態的DFS,回退到上一層DFS,即在 3 處考慮,此時 4 的路徑已經被標記過了

相當於:

1,2,3,4 -> 1,2,3,5 //直接從3考慮
而不是
1,2,3,4 -> 1,2,3 -> 1,2,3,5 //回溯多經過了一次3節點