题解 P2919 【[USACO08NOV]守护农场Guarding the Farm】

rt

若地图中一个元素所邻接的所有元素都比这个元素高度要小(或它邻接的是地图的边界),则该元素和其周围所有按照这样顺序排列的元素的集合称为一个小山丘。

那么我们可以用一个结构体类型记录所有非零高度的横纵坐标以及相应的高度值

然后对高度进行排序 对每一次高度进行\(dfs\) 及时删除所有的联通高度的小山丘

很显然 如果从一个给定高度的山丘的最高高度进行\(dfs\) 一定可以将该山丘的所有高度清零

犯了一个很zz的错误

在递归调用的时候 \(tmp\)定义的全局变量 然后在递归调用的时候 在下一次递归结束

之后 tmp的值已经被改变了 而当前层的tmp还未判断完成

我发誓我以后在\(dfs\)里面只用局部变量 手动再见

代码如下:

#include<bits/stdc++.h>
using namespace std;
int a[705][705],ans,px,py,tot,m,n;
int dx[]={0,0,1,1,1,-1,-1,-1};
int dy[]={1,-1,0,1,-1,0,1,-1};
struct p{
    int x,y,num;
}f[490005];
void dfs(int x,int y){
    int tmp=a[x][y];//在删除之前保存数据 
    //!!!每次循环都要调用tmp 在下一次递归结束之后 tmp的值已经被改变了 而当前层的tmp还未判断完成 
    a[x][y]=0;
    for (int i=0;i<=7;i++){
        px=x+dx[i];py=y+dy[i];
        if (px>0&&px<=n&&py>0&&py<=m&&tmp>=a[px][py]&&a[px][py]!=0) dfs(px,py);
    }
}
bool cmp(p a,p b){
    return a.num>b.num; 
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            if (a[i][j]) {
                tot++;
                f[tot].x=i;
                f[tot].y=j;
                f[tot].num=a[i][j];
            } 
        }
    sort(f+1,f+tot+1,cmp);
    for (int i=1;i<=tot;i++)
        if (a[f[i].x][f[i].y]) {//如果在删除过程当中没有被删除 
            ans++;
            dfs(f[i].x,f[i].y);
        } 
    printf("%d\n",ans);
    return 0;
}

posted @ 2019-05-06 15:36  dinghao1262  阅读(154)  评论(0编辑  收藏  举报