Hrbust 1517 Summits【Bfs+思维+贪心】好题~

寻找巅峰:地图上的算法挑战
本文介绍了一种算法挑战,旨在通过分析矩形网格地图中的高度数据来确定所谓的“d-巅峰”数量。该问题源于一场比赛,并通过一种特定的方法解决:先按高度排序地形点,再使用BFS遍历检查每个可能的巅峰。

Summits
Time Limit: 3000 MSMemory Limit: 65535 K
Total Submit: 8(5 users)Total Accepted: 5(5 users)Rating: Special Judge: No
Description

     You recently started working for the largest map drawing company in the Netherlands. Part of your job is to determine what the summits in a particular landscape are. Unfortunately, it is not so easy to determine which points are summits and which are not, because we do not want to call a small hump a summit. For example look at the landscape given by the sample input.

    We call the points of height 3 summits, since there are no higher points. But although the points of height 2, which are to the left of the summit of height 3, are all higher than or equalto their immediate neighbours, we do not want to call them summits, because we can reach a higher point from them without going to low (the summits of height 3). In contrast, we do want to call the area of height 2 on the right a summit, since if we would want to walk to the summit of height 3, we first have to descend to a point with height 0.

     After the above example, we introduce the concept of a d-summit. A point, with height h, is a d-summit if and only if it is impossible to reach a higher point without going through an area with height smaller than or equal to h−d.


    The problem is, given a rectangular grid of integer heights and an integer d, to find the number of d-summits.
Input
On the first line one positive number: the number of testcases, at most 100. After that per testcase:
• One line with three integers 1 ≤ h ≤ 500, 1 ≤ w ≤500 and 1 ≤ d ≤ 1 000 000 000. h and w are the dimensions of the map.d is as defined in the text.
• h lines with w integers, where the xth integer on the yth line denotes the height 0 ≤ h ≤ 1 000 000 000of the point (x, y).
Output
Per testcase:
• One line with the number of summits.
Sample Input
1
6 10 2
0 0 0 0 0 0 0 0 0 0
0 1 2 1 1 1 1 0 1 0
0 2 1 2 1 3 1 0 0 0
0 1 2 1 3 3 1 1 0 0
0 2 1 2 1 1 1 0 2 0
0 0 0 0 0 0 0 0 0 0
Sample Output
4
Source
NWERC2007

题目大意:

给你一个N*M的图,其中数字代表当前位子的山峰的高度。

我们的任务就是统计巅峰的个数,巅峰的定义:

以这个点作为起点,其如果能够走到比他高的点,那么这个点就不是巅峰,反之,如果能够走到的点都小于等于这个点的高度,那么这个点就是巅峰。

然而如何走有一个限制:以Z高度的点作为起点,能够走到的点的高度可以大于Z,但是如果小于Z,那么必须满足,起点的高度和这个点的高度差小于d.


思路:


1、我们如果直接暴力Bfs/Dfs明显是不可行的。那么我们考虑这样一点:

如果我们有一个坐标(x,y),是最高的巅峰(maxnx,maxny)能够走到的位子。而且还有一个坐标(x2,y2)能够走到这个坐标(x,y),那么很明显,(x2,y2)是能够走到坐标(maxnx,maxny)的。


2、根据上述特性,我们首先按照每个山峰的高度从大到小排序,然后我们从最高高度的山峰开始Bfs...........

如果对应当前起点能够走到的点是之前某高度的山峰走过的点,那么我们需要对其进行判断,这个点能够被最高的高度的山峰走到的高度是多少。

那么我们对应在Bfs的过程中维护一个数组manx【i】【j】表示点(i,j)能够被最高的山峰走到的高度为多少。

那么对应如果当前起点能够走到的点(i,j),其maxn【i】【j】==起点山峰高度,那么对应这个起点还可能是山峰,如果maxn【i】【j】>起点山峰高度,那么这个起点就一定不是巅峰。

那么我们每一次Bfs的时候,都统计和起点高度相同的山峰的个数,记做sum,如果对应当前起点的Bfs过程中没有出现(maxn【i】【j】>起点山峰高度)的情况,那么对应这sum个点都是巅峰。


3、注意一些细节,具体参考代码;


Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
struct node
{
    int x,y,val;
    friend bool operator <(node a,node b)
    {
        return a.val<b.val;
    }
}now,nex;
int maxn[555][555];
int a[555][555];
int vis[555][555];
int fx[4]={0,0,1,-1};
int fy[4]={1,-1,0,0};
int n,m,d,output;
void Bfs(int x,int y)
{
    int flag=0;
    now.x=x;
    now.y=y;
    maxn[x][y]=a[x][y];
    vis[x][y]=1;
    queue<node >s;
    s.push(now);
    int sum=0;
    while(!s.empty())
    {
        now=s.front();
        if(a[now.x][now.y]==a[x][y])sum++;
        s.pop();
        for(int i=0;i<4;i++)
        {
            nex.x=now.x+fx[i];
            nex.y=now.y+fy[i];
            if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m)
            {
                if(a[x][y]-a[nex.x][nex.y]>=d)continue;
                if(vis[nex.x][nex.y]==0)
                {
                    vis[nex.x][nex.y]=1;
                    maxn[nex.x][nex.y]=a[x][y];
                    s.push(nex);
                }
                else
                {
                    if(maxn[nex.x][nex.y]>a[x][y])flag=1;
                    maxn[nex.x][nex.y]=max(maxn[nex.x][nex.y],a[x][y]);
                }
            }
        }
    }
    if(flag==0)output+=sum;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(maxn,-1,sizeof(maxn));
        memset(vis,0,sizeof(vis));
        scanf("%d%d%d",&n,&m,&d);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        priority_queue<node >s;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                now.x=i;now.y=j,now.val=a[i][j];
                s.push(now);
            }
        }
        output=0;
        while(!s.empty())
        {
            now=s.top();
            s.pop();
            if(vis[now.x][now.y]==0)
            {
                Bfs(now.x,now.y);
            }
        }
        printf("%d\n",output);
    }
}
/*
6 10 2
0 0 0 0 0 0 0 0 0 0
0 1 2 1 1 1 1 0 1 0
0 2 1 2 1 3 1 0 0 0
0 1 3 1 3 3 1 1 0 0
0 2 1 2 1 1 1 0 2 0
0 0 0 0 0 0 0 0 0 0
5 5 2
0 2 0 2 0
0 0 0 0 0
0 2 0 2 0
0 0 0 0 0
0 2 0 2 0
5 5 100
0 2 0 2 0
0 0 0 0 0
0 2 0 2 0
0 0 0 0 0
0 2 0 2 0
*/






在充满仪式感的生活里,一款能传递心意的小工具总能带来意外惊喜。这款基于Java开发的满屏飘字弹幕工具,正是为热爱生活、乐于分享的你而来——它以简洁优雅的视觉效果,将治愈系文字化作灵动弹幕,在屏幕上缓缓流淌,既可以作为送给心仪之人的浪漫彩蛋,也能成为日常自娱自乐、舒缓心情的小确幸。 作为程序员献给crush的心意之作,工具的设计藏满了细节巧思。开发者基于Swing框架构建图形界面,实现了无边框全屏显示效果,搭配毛玻璃质感的弹幕窗口与圆润边角设计,让文字呈现既柔和又不突兀。弹幕内容精选了30条治愈系文案,从“秋天的风很温柔”到“你值得所有温柔”,涵盖生活感悟、自我关怀、浪漫告白等多个维度,每一条都能传递温暖力量;同时支持自定义修改文案库,你可以替换成专属情话、纪念文字或趣味梗,让弹幕更具个性化。 在视觉体验上,工具采用柔和色调生成算法,每一条弹幕都拥有独特的清新配色,搭配半透明渐变效果与平滑的移动动画,既不会遮挡屏幕内容,又能营造出灵动治愈的氛围。开发者还优化了弹幕的生成逻辑,支持自定义窗口大小、移动速度、生成间隔等参数,最多可同时显示60条弹幕,且不会造成电脑卡顿;按下任意按键即可快速关闭程序,操作便捷无负担。 对于Java学习者而言,这款工具更是一份优质的实战参考。源码完整展示了Swing图形界面开发、定时器调度、动画绘制、颜色算法等核心技术,注释清晰、结构简洁,哪怕是初学者也能轻松理解。开发者在AI辅助的基础上,反复调试优化细节,解决了透明度控制、弹幕碰撞、资源占用等多个问,这份“踩坑实录”也为同类项目开发提供了宝贵经验。 无论是想给喜欢的人制造浪漫惊喜,用满屏文字传递心意;还是想在工作间隙用治愈文案舒缓压力,或是作为Java学习的实战案例参考,这款满屏飘字弹幕工具都能满足你的需求。它没有复杂的操作流程,无需额外配置环境,下载即可运行,用最纯粹的设计传递最真挚的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值