🍑 算法题解专栏
🍑 山峰和山谷
题目描述
给定一个N*N的地图,每个方格(i,j)都有一个高度Wij。若两个方格有公共顶点,则称它们是相邻的。
例如,与(i,j)方格相邻的格子有(i−1, j−1),(i−1,j),(i−1,j+1),(i,j−1),(i,j+1),(i+1,j−1),(i+1,j),(i+1,j+1)。
定义山峰和山谷:
1、均由地图上一个连通块组成。连通块指块里任意方格与块中至少一个方格相邻。
2、连通块里所有方格高度相同。
3、连通块周围的方格(与其相邻但不属于连通块的方格)若高度均大于连通块的高度,则称连通块为山谷;若高度均小于则称连通块为山峰。
求地图里山谷和山峰的数量。
(注:如果整张地图的高度均相等,则整张地图既是一个山谷也是一个山峰。)
输入格式
第一行包含一个整数N,代表地图的大小。
接下来N行每行包含N个数,表示地图每个方格的高度。
输出格式
输出仅为一行,包含两个整数,分别为山峰和山谷的数量。
样例 #1
样例输入 #1
5
5 7 8 3 1
5 5 7 6 6
6 6 6 2 8
5 7 2 5 8
7 1 0 1 7
样例输出 #1
3 3
提示
山峰
5 7 8 3 1
5 5 7 6 6
6 6 6 2 8
5 7 2 5 8
7 1 0 1 7
山谷
5 7 8 3 1
5 5 7 6 6
6 6 6 2 8
5 7 2 5 8
7 1 0 1 7
【数据规模】
2<=N<=1000
🍑 输入超 10万 使用快读
🍑 库里的 Linkedlist 比 数组模拟队列 对内存的消耗更小,但运行时间会变长(猜测)
🍑 同一连通块的才需要判重
import java.io.*;
import java.util.*;
public class Main
{
static int N = 1010, n;
static int[][] h = new int[N][N];
static boolean[][] st = new boolean[N][N];
// static Node[] q = new Node[N * N];
static boolean hasLow, hasHigh;// 表示连通块周围有无比它低、高的点
static int[] dx = { -1, 0, 1, 0 };
static int[] dy = { 0, -1, 0, 1 };
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
static class Node
{
int x;
int y;
public Node(int x, int y)
{
super();
this.x = x;
this.y = y;
}
}
static void bfs(int sx, int sy)
{
st[sx][sy] = true;
int hh = 0;
int tt = -1;
// q[++tt] = new Node(sx, sy);
// LinkedList 相对于 数组模拟 队列 省空间
Queue<Node> q = new LinkedList<Node>();
q.add(new Node(sx, sy));
while (!q.isEmpty())
{
// Node t = q[hh++];
Node t = q.poll();
int x = t.x;
int y = t.y;
// st[x][y] = true;
for (int xx = x - 1; xx <= x + 1; xx++)
{
for (int yy = y - 1; yy <= y + 1; yy++)
{
if (xx < 0 || xx >= n || yy < 0 || yy >= n)
continue;
// AC 代码
//先处理特殊情况,无需判断是否是已经被遍历过的点
if (h[xx][yy] != h[x][y])
{
if (h[xx][yy] > h[x][y])
hasHigh = true;
else
hasLow = true;
}
//只有在处理同一连通块的点才需要判断是否有重复遍历
else if (!st[xx][yy])
{
st[xx][yy] = true;
// q[++tt] = new Node(xx, yy);
q.add(new Node(xx, yy));
}
// 代码2
// if (h[xx][yy] == h[x][y] && !st[xx][yy])
// {
// st[xx][yy] = true;
q[++tt] = new Node(xx, yy);
// q.add(new Node(xx, yy));
// } else
// {
// if (h[xx][yy] > h[x][y])
// hasHigh = true;
// else if (h[xx][yy] < h[x][y]) // 这里还是得避免 h[xx][yy] == h[x][y] 的情况
// hasLow = true;
// }
// 代码1
// if (h[xx][yy] < h[x][y])
// hasLow = true;
// else if (h[xx][yy] > h[x][y])
// hasHigh = true;
// else if (!st[xx][yy] && h[xx][yy] == h[x][y])
// {
// st[xx][yy] = true;// 只有同一个连通块才进行标记
q[++tt] = new Node(xx, yy);
// q.add(new Node(xx, yy));
// }
}
}
}
}
public static void main(String[] args) throws IOException
{
n = Integer.parseInt(in.readLine());
for (int i = 0; i < n; i++)
{
String[] ss = in.readLine().split(" ");
for (int j = 0; j < n; j++)
h[i][j] = Integer.parseInt(ss[j]);
}
int peek = 0;
int valley = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (!st[i][j])
{
hasLow = false;
hasHigh = false;
bfs(i, j);
if (!hasHigh)
peek++;
if (!hasLow)
valley++;
}
out.write(peek + " " + valley);
out.flush();
// System.out.println(peek + " " + valley);
}
}