UVA12130 Summits(BFS + 贪心)

UVA12130 Summits(BFS + 贪心)

题目链接

题目大意:

给你一个h ?
w 的矩阵,矩阵的每个元素都有一个值,代表这个位置的高度。题目要求你找出这个图中有多少个位置是峰值点。从每个点(高度H)出发遍历这个图有一个要求,就是走过的点的高度不能小于等于H - d;成为峰值点的要求就是从这个点出发走到的位置不能有高度大于H的。

解题思路:

因为图很大,用dfs肯定不行。将这些点按照高度从大到小的排序,然后每个点作为起点来遍历,如果找到比这个点大的点就说明不是峰值点。并且遍历的过程中就会将途中走过的点标记上它能到的最大高度。如果下次要找的这个点已经被标记过了,就说明这个点可以到达更大的高度,肯定不是峰值点,就不需要遍历。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 505;

int G[maxn][maxn];
int vis[maxn][maxn];//标记对于单独的一次遍历中是否有重复遍历的点,标记是否可以到达更大的高度
int n, m, d;

const int dir[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};

struct Node {

    int x, y, v;
}node[maxn * maxn], q[maxn * maxn];

int cmp (const Node &a, const Node &b) {
    return a.v > b.v;
}

int BFS (int k) {

    int front , rear;
    int cnt = 1;
    front = 0;
    rear = 1;
    q[front] = node[k];
    vis[node[k].x][node[k].y] = node[k].v;
    bool flag = 1;
    while (front < rear) {

        for (int i = 0; i < 4; i++) {

            int newx = q[front].x + dir[i][0];
            int newy = q[front].y + dir[i][1];
            if (newx < 0 || newx >= n || newy < 0 || newy >= m)
                continue;

            if (G[newx][newy] > node[k].v) {
                flag = 0;//往下继续遍历
                continue;
            }
            if (vis[newx][newy] == node[k].v || node[k].v - G[newx][newy] >= d)
                continue;
            vis[newx][newy] = node[k].v;
            if (G[newx][newy] == node[k].v)
                cnt++;
            else
                G[newx][newy] = node[k].v;
            q[rear].x = newx;
            q[rear++].y = newy;
        }
        front++;
    }
    if (flag)
        return cnt;
    return 0;
}

int main () {

    int T;
    scanf ("%d", &T);
    while (T--) {

        scanf ("%d%d%d", &n, &m, &d);
        int cnt = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) {
                scanf ("%d", &G[i][j]);
                node[cnt].x = i;
                node[cnt].y = j;
                node[cnt++].v = G[i][j];
            }

        sort (node, node + cnt, cmp);
        memset (vis, -1, sizeof (vis));
        int ans = 0;
        for (int i = 0; i < cnt; i++) {
            if (vis[node[i].x][node[i].y] == -1) {
                ans += BFS(i);
            }
        }

        printf ("%d\n", ans);
    }
    return 0;
}
时间: 2024-12-11 04:11:14

UVA12130 Summits(BFS + 贪心)的相关文章

UVA 12130 - Summits(BFS+贪心)

UVA 12130 - Summits 题目链接 题意:给定一个h * w的图,每个位置有一个值,现在要求出这个图上的峰顶有多少个.峰顶是这样定义的,有一个d值,如果一个位置是峰顶,那么它不能走到不大于该峰顶高度 - d的位置,如果满足这个条件下,并且无法走到更高的山峰,那么它就是峰顶 思路:利用贪心的策略,把所有点丢到优先队列,每次取出最高的峰值开始找,进行广搜,搜的过程中记录下最大值的点的个数,如果这个是峰顶,就加上这个数.判断是不是峰顶的方法为,如果广搜过程中,不会找到一个点的能到的最高峰

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

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

uva 12130 - Summits(BFS)

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

Hdu 4435 charge-station(BFS+贪心)

题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=4435 思路:编号大的点应尽量避免建立加油站(2^0+2^1+2^2+......+2^i<2^(i+1)),所以先假设全部建站,若此时仍不能满足题意,则无解.否则,从n开始枚举点,尝试该点不建立加油站是否能满足题意(dist[i]表示节点i到最近加油站的距离,若i不为加油站则若dist[i]*2>d则不符合题意(从某加油站出发到i,从i并不能返回加油).若i为加油站,则若从加油站1不能

hdu5335Walk Out bfs+贪心

//n行长度为m的01串, //从(1,1)走到(n,m)的所经过的点中形成的二进制数最小的为多少 //对于第一位是1,则只能往下和往右走, //每次处理距离终点距离一样的点,如果这样的点中有0那么只走0的点 //如果没有0的点,那么都要走 //对于第一位是0,那么先找到距离终点距离最近的1,再从那个点开始和 //上面一样的走 #include<cstdio> #include<cstring> #include<iostream> #include<string

UVALive - 3977 Summits (BFS染色)

题目大意:坑爹的题目,题意那么难理解. 讲的就是,如果该点是山顶的话(高度为h),那么以该点为中心,往外辐射,走高度大于h-d的点,到达不了另一个比它高的点 这就提示了,高度要从大到小排序,依次以高的点(假设高度为h)为核心辐射,如果碰上高度小于等于h-d的,表示此路不通了,就在该处停止 反之,如果碰上高度大于h-d的,且没有被染色过的,那么就将其染色 如果碰上高度大于h-d的,且被染色的话,就表明可以走到另一个更高点了,那么此点就不是山顶了 如果中途碰到了和该点一样高的,那么山顶的数量就加1

CodeForces - 986A Fair (BFS+贪心)

题意:有N个点M条边的无向图,每个点有给定的ai(1<=ai<=K,K<=200)表示该点拥有的物品编号,保证1-K在N个点全部出现.求每个点收集S个不同的物品所要走过的最短路程(边的长度为1). 分析:N是1e5,如果直接对每个点搜索肯定超时.发现K的范围很小,而且1-K全部覆盖.那么考虑对所有1-K的值BFS,用一个二维数组dp[i][j]记录i点要获取编号为j的物品最少走过的路程,并对每个点取最小的S个物品对应的路径. #include<bits/stdc++.h> u

HDU 5335 贪心+BFS

求从0,0点到n-1,m-1点的最小二进制数 分两种情况: 1:若0,0点为'1',则为起点,进bfs贪心 2:若0,0点为'0',则找出起点所连接的所有'0'点所能接触到的'1'点,取其中离终点曼哈顿距离最小的点当做起点,保证01串最短 bfs贪心:每次只往右或下方走,对所有能到达的新点,若有0,则只进是0的点,否则进1 #include "stdio.h" #include "string.h" #include "queue" using

零基础学贪心算法

本文在写作过程中参考了大量资料,不能一一列举,还请见谅.贪心算法的定义:贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解.贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关.解题的一般步骤是:1.建立数学模型来描述问题:2.把求解的问题分成若干个子问题:3.对每一子问题求解,得到子问题的局部最优解:4.把子问题的局部最优