【题解】降水


思路:

枚举每一层(层数要取所有高度中最高的)。设当前枚举到了第 $i$ 层:

       STEP 1:则遍历所有点,把高度高于或等于 $i$ 的点标记为 $1$,反之,标记为 $0$。

       STEP 2 : 然后找出被 $1$ 包围的 $0$ 的个数(用 dfs),加到 $ans$ 里。最后输出 $ans$ 即可。

                      对于 STEP 2 来说,把四周的点作为起点,进行 dfs,只要 visit 过的点就标记为 $1$。最后再遍历一遍所有点,统计 $0$ 的个数。

代码:

#include
using namespace std;

int n,m;
int mapn[109][109];
int nown[109][109];
int maxn = -1;
int ans=0;
int nexts[10][3] = {{0,1},{1,0},{0,-1},{-1,0}};

void dfs(int r,int c){
    nown[r][c] = 1;
    int nr,nc;
    for(int i=0; i<4; i++){
        nr = r+nexts[i][0];
        nc = c+nexts[i][1];
        if(nr > n || nr < 1 || nc > m || nc < 1 || nown[nr][nc] == 1)continue;
        nown[nr][nc] = 1;
        dfs(nr,nc);
    }
}

void func(){
    for(int i=1; i<=m; i++)
        if(nown[1][i] == 0)dfs(1,i);
    for(int j=1; j<=n; j++){
        if(nown[j][1] == 0)dfs(j,1);
        if(nown[j][m] == 0)dfs(j,m);
    }
    for(int i=1; i<=m; i++)
        if(nown[n][i] == 0)dfs(n,i);
}

int main(){
    cin >> n >> m;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            cin >> mapn[i][j];
            maxn = max(mapn[i][j],maxn);
        }
    }

    for(int l=1; l<=maxn; l++){//枚举每一层
        int tmp = 0;
        for(int i=1; i<=n; i++){
            for(int j=1; j<=m; j++){
                if(mapn[i][j] >= l) nown[i][j] = 1;
                else nown[i][j] = 0;
            }
        }

        func();

        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                if(nown[i][j] == 0) 
                    ans++;
    }
    cout << ans;
    return 0;
}