1.ACW1097:池塘计数
题意:‘W’:水、’.’:干的,求水坑数。
思路:最基本的Floodfill。
代码如下:
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 1010;
typedef long long LL;
typedef pair<LL, LL> PII;
char c[N][N];
LL n,m;
bool st[N][N];
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
void bfs(LL sta,LL ed)
{
queue<PII>q;q.push({sta,ed});st[sta][ed]=true;
while(q.size())
{
PII t=q.front();q.pop();
for(int i=0;i<8;i++)
{
LL ix=t.x+dx[i],iy=t.y+dy[i];
if(ix<=0||iy<=0||ix>n||iy>m||st[ix][iy]||c[ix][iy]=='.') continue;
q.push({ix,iy});st[ix][iy]=true;
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) cin>>c[i][j];
LL ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!st[i][j]&&c[i][j]=='W')
{
bfs(i,j);
ans++;
}
cout<<ans;
return 0;
}
2.ACW1098:城堡问题
题意:每个格子由一个数字表示其四个方向哪个方向存在墙,不存在墙的两格子间即连通为一个房间,求最大房间数量。其中,1:西墙、2:北墙、3:东墙、4:南墙,【可累加,例如:四个墙都存在这个格子即为15。】
思路:不必建图,发现按二进制判断格子的每一位是否为1,为1则表示该格子在当前对应方位有墙,因此与这个方向上的隔壁格子构不成连通,这个格子自然不加进队列。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define x first
#define y second
using namespace std;
const int N = 55;
typedef long long LL;
typedef pair<int, int> PII;
LL c[N][N],n,m,t,res;
bool st[N][N];
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
void bfs(LL sta,LL ed)
{
queue<PII>q;q.push({sta,ed});st[sta][ed]=true;LL area=0;
while(q.size())
{
PII t=q.front();q.pop();area++;
for(int i=0;i<4;i++)
{
LL ix=t.x+dx[i],iy=t.y+dy[i];
if(ix<1||iy<1||ix>n||iy>m||st[ix][iy]) continue;
if(!(c[t.x][t.y]>>i&1)) {q.push({ix,iy});st[ix][iy]=true;}
}
}
res=max(area,res);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) cin>>c[i][j];
LL ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!st[i][j]) {bfs(i,j);ans++;}
cout<<ans<<endl;
cout<<res;
return 0;
}
3.ACW1106:山峰和山谷
题意:
我们定义一个格子的集合 S 为山峰(山谷)当且仅当:
①S 的所有格子都有相同的高度。
②S 的所有格子都连通。
③对于 s 属于 S,与 s 相邻的 s′ 不属于 S,都有 ws>ws′(山峰),或者 ws<ws′(山谷)。
④如果周围不存在相邻区域,则同时将其视为山峰和山谷。
思路:Floodfill找出每个连通块,并标记该连通块所紧邻的点有无比它大的、有无比它小的:
①若有比它大的,也有比它小的格子:这个连通块既不是山峰也不是山谷。
②若只有比它大的,无比它小的:这个连通块是山谷。
③若只有比它小的,无比它大的:这个连通块是山峰。
④若既无比它大的,也无比它小的,即与当前连通块中所有格子相等:这些与连通块相等的格子也是连通块中的一部分。
代码如下:
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 1010;
typedef long long LL;
typedef pair<int, int> PII;
LL c[N][N],n,m,t,low,peak;
bool st[N][N];
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
void bfs(LL x,LL y,bool &has_high,bool &has_low)
{
queue<PII>q;q.push({x,y});st[x][y]=true;
while(q.size())
{
PII t=q.front();q.pop();
for(int i=0;i<8;i++)
{
LL ix=t.x+dx[i],iy=t.y+dy[i];
if(ix<1||iy<1||ix>n||iy>n) continue;
if(c[ix][iy]>c[t.x][t.y]) has_low=true;
else if(c[ix][iy]<c[t.x][t.y]) has_high=true;
else if(c[ix][iy]==c[t.x][t.y])
{
if(!st[ix][iy]) {q.push({ix,iy});st[ix][iy]=true;}
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) cin>>c[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!st[i][j])
{
bool has_high=false,has_low=false;
bfs(i,j,has_high,has_low);
if(!has_low) peak++;
if(!has_high) low++;
}
cout<<peak<<' '<<low;
return 0;
}