1. 程式人生 > >[nowcoder]218-A 地、顏色、魔法

[nowcoder]218-A 地、顏色、魔法

連結:https://ac.nowcoder.com/acm/contest/218/A
來源:牛客網

題目描述

紅色來源於山脈,象徵著狂躁、憤怒、混亂,血雨腥風,電光火石。
藍色來源於海島,象徵著控制、幻覺、詭計,運籌帷幄,謀定後動。
綠色來源於樹林,象徵著生命、蠻力、成長,橫衝直撞,生生不息。
黑色來源於沼澤,象徵著死亡、貪婪、腐敗,追求卓越,不計代價。
白色來源於平原,象徵著秩序、公平、正義,攜手共進,穩中求勝。

現在,你作為一名新星鵬洛客,找到了一塊絕佳的修煉地。這塊地方可以被描述成一個 n x m 的矩形。你已經在這塊地中的一些位置打好了標記。接下去,就該對整塊地賦予你的顏色了。一個位置能被賦予你的顏色,當且僅當滿足以下條件之一:

  1. 這個位置被打上了標記。
  2. 這個位置在不經過被打標記的位置的情況下與邊界不連通(這個圖是四聯通的)。換句話說,如果你從這個位置開始,在不經過被打標記的位置,且只能向上下左右四個方向移動的情況下永遠不能走到地圖的邊界,那麼這個位置符合條件。 現在,你的好基友想知道,你能為多少個位置賦予你自己的顏色呢?

輸入描述:
第一行包含兩個正整數 n, m ,表示地圖的長和寬。
接下去 n 行,每行一個長為 m 的字串,表示地圖的一行。
其中 ,表示該位置未被打標記“ . ” 表示該位置被打了標記“#”。
保證地圖僅由“ . ” 和“#”構成。
輸出描述:
輸出僅一行,包含一個整數,表示你的答案。

樣例輸入

4 4
. . . .
.###
.# .#
.###

樣例輸出

9

說明
可以被賦予顏色的位置在下圖中用@標出了。

. . . .
[email protected]@@
[email protected]@@
[email protected]@@

備註:
1 ≤ n x m ≤ 10^6

一開始我對題意的理解不知有什麼鍋鍋,認為可以掃一下外圍帶“ . ”的連通塊,然後把剩下的標成“@”結果,完美的WA掉了(20分)

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
int n,m;
char ch[10001][10001];
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
inline void dfs(int x,int y){
    ch[x][y]='*';
    for(int i=1;i<=4;i++){
        int sx=x+dx[i];
        int sy=y+dy[i];
        if(ch[sx][sy]=='#'&&ch[sx][sy]=='@') continue;
        if(ch[sx][sy]=='.') dfs(sx,sy);
    }
}
int main(){
    int ans=0;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%s",ch[i]+1);
    dfs(1,1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(ch[i][j]=='.'||ch[i][j]=='#') ch[i][j]='@';
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(ch[i][j]=='@') ans++;
    printf("%d",ans);
    return 0;
}

我又讀了一遍題目,發現可以從一個點出發,從這個點向外掃連通塊,結果還是有用的,70分……

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
bool flag;
int n,m,cnt;
char ch[10001][10001];
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
inline void dfs(int x,int y){
    ch[x][y]='*';cnt++;
    for(int i=1;i<=4;i++){
        int sx=x+dx[i];
        int sy=y+dy[i];
        if(sx<1||sx>n||sy<1||sy>m) {
            flag=false;
            return ;
        }
        if(ch[sx][sy]=='#'&&ch[sx][sy]=='@') continue;
        if(ch[sx][sy]=='.') dfs(sx,sy);
    }
}
int main(){
    int ans=0;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%s",ch[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(ch[i][j]=='#') ans++;
            else if(ch[i][j]=='.'){
                flag=true;
                cnt=0;
                dfs(i,j);
                if(flag) ans+=cnt;
            }
        }
    printf("%d",ans);
    return 0;
}

當時我就在想:什麼毒瘤資料卡我點!
再讀題n*m≤10^6,這是什麼情況!肯定會炸掉啊,只能vector存圖了,只要TA超過了邊界就直接break。(80分?嗯?什麼情況?你怎麼回事?)

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
bool flag;
int n,m,cnt;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
vector<char> ch[1000001];
inline void dfs(int x,int y){
    ch[x][y]='*';cnt++;
    for(int i=1;i<=4;i++){
        int sx=x+dx[i];
        int sy=y+dy[i];
        if(sx<0||sx>n-1||sy<0||sy>m-1) {
            flag=false;
            return ;
        }
        if(ch[sx][sy]=='#'&&ch[sx][sy]=='@') continue;
        if(ch[sx][sy]=='.') dfs(sx,sy);
    }
}
int main(){
    int ans=0;
    char str;
    scanf("%d %d",&n,&m);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            scanf(" %c",&str);
            ch[i].push_back(str);
        }
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            if(ch[i][j]=='#') ans++;
            else if(ch[i][j]=='.'){
                flag=true;
                cnt=0;
                dfs(i,j);
                if(flag) ans+=cnt;
            }
        }
    printf("%d",ans);
    return 0;
}

這也太不厚道了吧……我又仔細想想,出了機組極端資料卡我那可愛的程式,發現超過邊界只能continue才能搜到更多的不符合要求的點,AC程式碼如下:

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
bool flag;
int n,m,cnt;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
vector<char> ch[1000001];
inline void dfs(int x,int y){
    ch[x][y]='*';cnt++;
    for(int i=1;i<=4;i++){
        int sx=x+dx[i];
        int sy=y+dy[i];
        if(sx<0||sx>n-1||sy<0||sy>m-1) {
            flag=false;
            continue ;
        }
        if(ch[sx][sy]=='#') continue;
        if(ch[sx][sy]=='.') dfs(sx,sy);
    }
}
int main(){
    int ans=0;
    char str;
    scanf("%d %d",&n,&m);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            scanf(" %c",&str);
            ch[i].push_back(str);
        }
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            if(ch[i][j]=='#') ans++;
            else if(ch[i][j]=='.'){
                flag=true;
                cnt=0;
                dfs(i,j);
                if(flag) ans+=cnt;
            }
        }
    printf("%d",ans);
    return 0;
}

我還是太弱了啊,一道Dfs的大水題都讓我做個半天,繼續學習去嘍