UVA 12130 - Summits(BFS+贪心)

UVA 12130 - Summits

题目链接

题意:给定一个h * w的图,每个位置有一个值,现在要求出这个图上的峰顶有多少个。峰顶是这样定义的,有一个d值,如果一个位置是峰顶,那么它不能走到不大于该峰顶高度 - d的位置,如果满足这个条件下,并且无法走到更高的山峰,那么它就是峰顶

思路:利用贪心的策略,把所有点丢到优先队列,每次取出最高的峰值开始找,进行广搜,搜的过程中记录下最大值的点的个数,如果这个是峰顶,就加上这个数。判断是不是峰顶的方法为,如果广搜过程中,不会找到一个点的能到的最高峰值大于它,那么它就是峰顶,可以在广搜过程边广搜边记录下每个点能到的最大高度,然后这样一来,其实每个点都只会搜到一次,复杂度为O(h
w log(h * w))

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;

const int N = 505;
const int D[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

int t, h, w, d, g[N][N], vis[N][N];

struct Point {
    int x, y, val;
    Point(int x, int y, int val = 0) {
	this->x = x;
	this->y = y;
	this->val = val;
    }
    bool operator < (const Point& a) const {
	return val < a.val;
    }
};

priority_queue<Point> Q;

int bfs(int x, int y, int H) {
    queue<Point> Q;
    Q.push(Point(x, y));
    vis[x][y] = H;
    int ans = 1;
    int flag = 1;
    while (!Q.empty()) {
	Point u = Q.front();
	Q.pop();
	for (int i = 0; i < 4; i++) {
	    int xx = u.x + D[i][0];
	    int yy = u.y + D[i][1];
	    if (xx < 0 || xx >= h || yy < 0 || yy >= w) continue;
	    if (H - g[xx][yy] >= d) continue;
	    if (vis[xx][yy] > H) {
		flag = 0;
		continue;
	    }
	    if (vis[xx][yy] == H) continue;
	    if (g[xx][yy] == H) ans++;
	    vis[xx][yy] = H;
	    Q.push(Point(xx, yy));
	}
    }
    if (flag) return ans;
    return 0;
}

int solve() {
    memset(vis, -1, sizeof(vis));
    int ans = 0;
    while (!Q.empty()) {
	Point u = Q.top();
	Q.pop();
	if (vis[u.x][u.y] != -1) continue;
	ans += bfs(u.x, u.y, g[u.x][u.y]);
    }
    return ans;
}

int main() {
    scanf("%d", &t);
    while (t--) {
	scanf("%d%d%d", &h, &w, &d);
	for (int i = 0; i < h; i++) {
	    for (int j = 0; j < w; j++) {
		scanf("%d", &g[i][j]);
		Q.push(Point(i, j, g[i][j]));
	    }
	}
	printf("%d\n", solve());
    }
    return 0;
}

UVA 12130 - Summits(BFS+贪心),布布扣,bubuko.com

时间: 2024-12-19 20:07:12

UVA 12130 - Summits(BFS+贪心)的相关文章

uva 12130 - Summits(BFS)

题目链接:uva 12130 - Summits 题目大意:给定一个N?M的图,每个位置有一个值.给定D,表示有节点值为G的位置作为起点的话,将不能移动到值小于等于G?D的节点.现在要求找到整个图中所有的峰值点,峰值点的定义是不能移动到比自己节点值大的位置. 解题思路:将每个位置按照权值排序,逐个作为起点进行移动,v[x][y]数组值可以到达x,y的节点的值的最大值,如果起始点可以移动到v[x][y]大于本身的点,则说明该起点不是峰值点. #include <cstdio> #include

UVA - 12130 Summits

Description Problem G - Summits Time limit: 8 seconds You recently started working for the largest map drawing company in theNetherlands. Part of your job is to determine what the summits in aparticular landscape are. Unfortunately, it is not so easy

UVA12130 Summits(BFS + 贪心)

UVA12130 Summits(BFS + 贪心) 题目链接 题目大意: 给你一个h ? w 的矩阵,矩阵的每个元素都有一个值,代表这个位置的高度.题目要求你找出这个图中有多少个位置是峰值点.从每个点(高度H)出发遍历这个图有一个要求,就是走过的点的高度不能小于等于H - d:成为峰值点的要求就是从这个点出发走到的位置不能有高度大于H的. 解题思路: 因为图很大,用dfs肯定不行.将这些点按照高度从大到小的排序,然后每个点作为起点来遍历,如果找到比这个点大的点就说明不是峰值点.并且遍历的过程中

UVA 10317 - Equating Equations 贪心 dfs

UVA 10317 - Equating Equations 贪心 dfs ACM 题目地址:UVA 10317 - Equating Equations 题意: 给一个等式,但是这个等式不一定是正确的,要你对等式中的数字重新排序,使得等式成立.等式只有+和-,数字个数小于16. 分析: 以a + b - c = d - e为例子. 1. 我们把等式右边的各项都换到左边,a + b - c - d + e = 0 2. 把+项和-项放一起,就变成(a + b + e) - (c + d) = 0

uva 1534 - Taekwondo(dp+贪心)

题目连接:uva 1534 - Taekwondo 题目大意:有两组什么东西,题目背景有点忘记了,就是给出两组数,两组个数分别为n,m,要求找出min(n,m)对数,每个数最多最多选一次,使得这min(n,m)对数ai,bi,ai-bi的绝对值之和最小. 解题思路:贪心,将两组数分别排序,然后dp[i][j]表示i对,匹配到j时候的最优解. #include <cstdio> #include <cstring> #include <cmath> #include &l

UVA 1422 - Processor (二分+贪心+优先队列)

先对开始时间进行排序,在利用优先队列是结束时间早点先出队: 因为时间只有20000,我们可以去枚举每个单位时间,看要给分配给那个任务, 如果某个时间队列中还有结束时间大于枚举的时间,就跳出判断是在mid的右边. #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<stdlib.h> #include<math.h> #

uva 1372 - Log Jumping(贪心)

题目链接:uva 1372 - Log Jumping 题目大意:给出n,k,表示有n个木板和长度均为k,现在给出所有木板的左边位置,如果两块木板有重叠,那么就可以在两块木板之间移动,问说最多能形成的最大块数的环. 解题思路:将木块按照左边界排序,每次如果i块板和i-1,i-2有重叠,那么i块板也可以加入环. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; co

uva 10020- Minimal coverage (贪心思想 简单区间覆盖)

题目大意:给出一个范围M,然后给出若干的区间,以0 0 终止, 要求用最少的区间将0 ~M 覆盖,输出最少个数以及方案. 解题思路:典型的区间覆盖问题,算法竞赛入门经典P154上有讲. /*author: charkj_z */ /*time: 0.108s */ /*rank: 674 */ /*为什么不把没用的地方去掉? 因为去掉了我觉得不像我能写出来的*/ /*Ac code : */ #include<stdio.h> #include<string.h> #include

luogu 1066 引水入城(bfs+贪心)

90分,有一个点TLE.... 首先可以证明一个东西,如果从上面一排的某个点bfs一次到最下面一排的饮水点不是一个区间的话,那么最后一定所有饮水点不会被覆盖完的. 证明考虑反证法. 所以从上面一排的每个点bfs一次得到一个区间.题目转化为给出m个区间覆盖m个点的最小区间选择数. 显然是个明显的贪心,以左区间端点为第一关键字升序排序,右区间端点为第二关键字降序排序,那么每次贪心的选择一个覆盖最大的区间即可. 时间复杂度O(n*m^2+mlogm).需要常数优化. # include <cstdio