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

链接:https://ac.nowcoder.com/acm/contest/218/A
来源:牛客网

题目描述

红色来源于山脉,象征着狂躁、愤怒、混乱,血雨腥风,电光火石。
蓝色来源于海岛,象征着控制、幻觉、诡计,运筹帷幄,谋定后动。
绿色来源于树林,象征着生命、蛮力、成长,横冲直撞,生生不息。
黑色来源于沼泽,象征着死亡、贪婪、腐败,追求卓越,不计代价。
白色来源于平原,象征着秩序、公平、正义,携手共进,稳中求胜。

现在,你作为一名新星鹏洛客,找到了一块绝佳的修炼地。这块地方可以被描述成一个 n x m 的矩形。你已经在这块地中的一些位置打好了标记。接下去,就该对整块地赋予你的颜色了。一个位置能被赋予你的颜色,当且仅当满足以下条件之一:

  1. 这个位置被打上了标记。
  2. 这个位置在不经过被打标记的位置的情况下与边界不连通(这个图是四联通的)。换句话说,如果你从这个位置开始,在不经过被打标记的位置,且只能向上下左右四个方向移动的情况下永远不能走到地图的边界,那么这个位置符合条件。 现在,你的好基友想知道,你能为多少个位置赋予你自己的颜色呢?

输入描述:
第一行包含两个正整数 n, m ,表示地图的长和宽。
接下去 n 行,每行一个长为 m 的字符串,表示地图的一行。
其中 ,表示该位置未被打标记“ . ” 表示该位置被打了标记“#”。
保证地图仅由“ . ” 和“#”构成。
输出描述:
输出仅一行,包含一个整数,表示你的答案。

样例输入

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

样例输出

9

说明
可以被赋予颜色的位置在下图中用@标出了。

. . . .
.@@@
.@@@
.@@@

备注:
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的大水题都让我做个半天,继续学习去喽

猜你喜欢

转载自blog.csdn.net/MercedesAMGE63s/article/details/84178469