整理的算法模板:ACM算法模板總結(分類詳細版)
FGD小朋友特別喜歡爬山,在爬山的時候他就在研究山峯和山谷。
爲了能夠對旅程有一個安排,他想知道山峯和山谷的數量。
給定一個地圖,爲FGD想要旅行的區域,地圖被分爲 n×nn×n 的網格,每個格子 (i,j)(i,j) 的高度 w(i,j)w(i,j) 是給定的。
若兩個格子有公共頂點,那麼它們就是相鄰的格子,如與 (i,j)(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)(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)。
我們定義一個格子的集合 SS 爲山峯(山谷)當且僅當:
- SS 的所有格子都有相同的高度。
- SS 的所有格子都連通。
- 對於 ss 屬於 SS,與 ss 相鄰的 s′s′ 不屬於 SS,都有 ws>ws′ws>ws′(山峯),或者 ws<ws′ws<ws′(山谷)。
- 如果周圍不存在相鄰區域,則同時將其視爲山峯和山谷。
你的任務是,對於給定的地圖,求出山峯和山谷的數量,如果所有格子都有相同的高度,那麼整個地圖即是山峯,又是山谷。
輸入格式
第一行包含一個正整數 nn,表示地圖的大小。
接下來一個 n×nn×n 的矩陣,表示地圖上每個格子的高度 ww。
輸出格式
共一行,包含兩個整數,表示山峯和山谷的數量。
數據範圍
1≤n≤10001≤n≤1000,
0≤w≤1090≤w≤109
輸入樣例1:
5
8 8 8 7 7
7 7 8 8 7
7 7 7 7 7
7 8 8 7 8
7 8 8 8 8
輸出樣例1:
2 1
輸入樣例2:
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
輸出樣例2:
3 3
樣例解釋
樣例1:
樣例2:
難度:中等 |
時/空限制:1s / 64MB |
總通過數:449 |
總嘗試數:868 |
來源:《信息學奧賽一本通》 , POI2007 |
算法標籤 Food fill |
枚舉每一個點進行bfs,當這個bfs時當前點周圍有比他高的點的話就flag標記一下,同理有比他低的點也flag標記一下;在Food fill的基礎上增加了對每個點周圍點的判斷,總體還是板子題;
跟着y總學會一個點八個方位的遍歷方法:
x-1,y-1 | x-1,y | x-1,y+1 |
x,y-1 | x,y | x,y+1 |
x+1,y-1 | x+1,y | x+1,y+1 |
二重數組遍歷這9個點即可;
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=1005;
int mp[N][N],hight,lower,n,a,b;
bool st[N][N];
void bfs(int x,int y)
{
queue<PII> q;
q.push({x,y});
st[x][y];
while(!q.empty())
{
auto res=q.front();
int xx=res.first,yy=res.second;
q.pop();
for(int i=xx-1;i<=xx+1;i++)
{
for(int j=yy-1;j<=yy+1;j++)
{
if(i<0||i>=n||j<0||j>=n) continue;
if(mp[i][j]!=mp[xx][yy])
{
if(mp[i][j]>mp[xx][yy]) hight=1;
else lower=1;
}
else if(!st[i][j])
{
q.push({i,j});
st[i][j]=true;
}
}
}
}
}
int main()
{
cin >>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) cin >>mp[i][j];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(!st[i][j])
{
hight=0,lower=0;
bfs(i,j);
if(!hight) a++;
if(!lower) b++;
}
}
}
cout <<a<<" "<<b<<endl;
}