[USACO08NOV] Guarding the Farm S(dfs类flood fill但含限制)

[USACO08NOV] Guarding the Farm S

题面翻译

农夫 John 的农场里有很多小山丘,他想要在那里布置一些保镖去保卫他的那些相当值钱的奶牛们。

他想知道如果在一座小山丘上布置一名保镖的话,他最少总共需要招聘多少名保镖。他现在手头有一个用数字矩阵来表示地形的地图。这个矩阵有 N N N 行和 M M M 列。矩阵中的每个元素都有一个值 H i j H_{ij} Hij 来表示该地区的海拔高度。

小山丘的定义是:若地图中一个元素所邻接的所有元素都小于等于这个元素的高度(或它邻接的是地图的边界),则该元素和其周围所有按照这样顺序排列的元素的集合称为一个小山丘。这里邻接的意义是:若一个位置的横纵坐标与另一个位置的横纵坐标相差不超过 1 1 1,则称这两个元素邻接,比如某个非边界点的位置有 8 8 8 个相邻点:上、下、左、右、左上、右上、左下、右下。

请你帮助他统计出地图上最少且尽量高的小山丘数量。

题目描述

The farm has many hills upon which Farmer John would like to place guards to ensure the safety of his valuable milk-cows.

He wonders how many guards he will need if he wishes to put one on top of each hill. He has a map supplied as a matrix of integers; the matrix has N (1 < N <= 700) rows and M (1 < M <= 700) columns. Each member of the matrix is an altitude H_ij (0 <= H_ij <= 10,000). Help him determine the number of hilltops on the map.

A hilltop is one or more adjacent matrix elements of the same value surrounded exclusively by either the edge of the map or elements with a lower (smaller) altitude. Two different elements are adjacent if the magnitude of difference in their X coordinates is no greater than 1 and the magnitude of differences in their Y coordinates is also no greater than 1.

输入格式

* Line 1: Two space-separated integers: N and M

* Lines 2…N+1: Line i+1 describes row i of the matrix with M

space-separated integers: H_ij

输出格式

* Line 1: A single integer that specifies the number of hilltops

样例 #1

样例输入 #1

8 7 
4 3 2 2 1 0 1 
3 3 3 2 1 0 1 
2 2 2 2 1 0 0 
2 1 1 1 1 0 0 
1 1 0 0 0 1 0 
0 0 0 1 1 1 0 
0 1 2 2 1 1 0 
0 1 1 1 2 1 0

样例输出 #1

3

提示

There are three peaks: The one with height 4 on the left top, one of the points with height 2 at the bottom part, and one of the points with height 1 on the right top corner.

思路

这道题可不是单纯的 flood fill 模型,因为它有高度限制,即:若地图中一个元素所邻接的所有元素都小于等于这个元素的高度(或它邻接的是地图的边界),则该元素和其周围所有按照这样顺序排列的元素的集合称为一个小山丘。因此我们用dfs来模拟flood fill的做法个人感觉更好想:

  • 让 dfs 的返回值为 bool ,如果不满足上述式子,我们就让标记为false,这样返回出来的值就是false,此时就不记录作为答案。也就是:就是大力枚举每一个色块,判断色块是否为答案。
  • 当前点的附近如果有比它高的点,那么就不是我们的答案了。为什么呢?因为它不能作为最高点了(也就是顶峰),其实本道题实质上就是求顶峰的个数。

具体写法

#include<iostream>
#include<cstring>
#define int long long
using namespace std;

const int N = 1010;

int w[N][N];
int n,m;
int dx[]={0,1,1,1,0,-1,-1,-1};
int dy[]={1,1,0,-1,-1,-1,0,1};
bool st[N][N];

bool dfs(int x,int y){
    //这种有限制的用bfs有点复杂
    bool f=true;
    
    st[x][y]=true;//被遍历过就不要再遍历了
    
    for(int i=0;i<8;i++){
        int a=dx[i]+x,b=dy[i]+y;
        if(a<1||b<1||a>n||b>m) continue;
        if(w[a][b]>w[x][y]) f=false;//当前点的附近如果有比它高的点,那么就不是我们的答案了
        if(w[a][b]==w[x][y]&&!st[a][b]){
            f&=dfs(a,b);
            //这边假设一个情况,就是如果坐标(x,y)附近如果一旦有高度比它高的,那么此时就不能记录答案了
        }
    }
    
    return f;
}

signed main(){
    cin>>n>>m;
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>w[i][j];
        }
    }
    
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(!st[i][j]){
                if(dfs(i,j)) ans++;
            }
        }
    }
    
    cout<<ans;
    
    return 0;
    
}

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

green qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值