题目大意:给定一个N∗M的图,每个位置有一个值。给定D,表示有节点值为G的位置作为起点的话,将不能移动到值小于等于G−D的节点。现在要求找到整个图中所有的峰值点,峰值点的定义是不能移动到比自己节点值大的位置。
解题思路:将每个位置按照权值排序,逐个作为起点进行移动,v[x][y]数组值可以到达x,y的节点的值的最大值,如果起始点可以移动到v[x][y]大于本身的点,则说明该起点不是峰值点。
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 505;
const int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
struct point {
int x, y, val;
point (int x = 0, int y = 0, int val = 0) {
this->x = x;
this->y = y;
this->val = val;
}
bool operator < (const point& u) const {
return val > u.val;
}
};
int N, M, D, g[maxn][maxn], v[maxn][maxn];
vector<point> vec;
void init () {
vec.clear();
memset(v, 0, sizeof(v));
scanf("%d%d%d", &N, &M, &D);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
scanf("%d", &g[i][j]);
vec.push_back(point(i, j, g[i][j]));
}
}
sort(vec.begin(), vec.end());
}
int bfs (int x, int y, int h) {
int ret = 1;
bool flag = true;
queue<point> que;
que.push(point(x, y));
while (!que.empty()) {
point u = que.front();
que.pop();
for (int i = 0; i < 4; i++) {
int p = u.x + dir[i][0];
int q = u.y + dir[i][1];
if (p <= 0 || p > N || q <= 0 || q > M)
continue;
if (h - g[p][q] >= D)
continue;
if (v[p][q] > h) {
flag = false;
continue;
}
if (v[p][q] == h)
continue;
if (g[p][q] == h)
ret++;
v[p][q] = h;
que.push(point(p, q));
}
}
//printf("%d %d %d %d\n", x, y, g[x][y], ret);
if (flag == false)
return 0;
return ret;
}
int solve () {
int ret = 0;
for (int i = 0; i < vec.size(); i++) {
int x = vec[i].x, y = vec[i].y;
if (v[x][y])
continue;
v[x][y] = g[x][y];
ret += bfs(x, y, g[x][y]);
}
return ret;
}
int main () {
int cas;
scanf("%d", &cas);
while (cas--) {
init();
printf("%d\n", solve());
}
return 0;
}