作者:乐天JOE
题目背景
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了 F-2003飞机。
此外,巡洋船只和舰队将被派去保护海岸线。不幸的是,因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们培养了一些新海军指挥官。军官们选择了“海战”游戏来帮助他们学习。
题目描述
在一个方形的盘上,放置了固定数量和形状的船只,每只船却 不能碰到 其它的船。在本题中,我们认为船是 方形 的,所有的船只都是由图形组成的方形。
求出该棋盘上放置的船只的 总数 。
输入格式
第一行为两个整数 R 和 C,用空格隔开,分别表示游戏棋盘的行数和列数。
接下来 R 行,每行 C 个字符,为 # 或 . 。# 表示 船只 的一部分,. 表示 水 。
输出格式
一行一个字符串,如果船的位置放得正确(即棋盘上只存在 相互之间不能接触 的方形,如果两个 # 号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出 There are S ships. ,S 表示船只的数量。否则输出 Bad placement. 。
样例 #1
样例输入 #1
6 8
.....#.#
##.....#
##.....#
.......#
#......#
#..#...#
样例输出 #1
There are 5 ships.
提示
对于的数据,
。
思路
看到题目,似乎就是求联通块的问题。但有个问题:该如何判断连在一起的船只呢?那我们不妨把问题分为 爆搜与判断 。
爆搜
bfs或dfs求联通块的问题很简单,但还是给想我这样的蒟蒻讲一下(懂得请跳过)。
首先遍历整个地图,然后只要找到船只,就把答案加一。
接着就开始从这个点开始 洪水填充 (如果这个都不知道请先看一下这篇文章),每次遍历的时候记得把他设定为走过,我在这里卡了好久,这样这个地方就处理好了。
最后输出答案
判断连在一起的船只
有两种方法
方法一
观察以下几组需要输出 bad placement. 的数据:
. . # . .
. . # . .
. . # # .
. . # # .
. . . # .
. . . # .
. . . # # # # . . .
. . . . . # # # # #
. . . . . . . . . .
. # . .
. # . .
. # . .
. # # .
. . # .
. . # .
. . # #
. . . #
. . . #
被我划线的部分都是影响船只不接触的地方,那我们把他们 化成最简 ,就会变成这个图形
. #
# #
那我们就只需要判断 是否有这个图形 出现就行了
方法二
由于船只必须是方形,所以我们只需要在联通的时候判断有几个角,而且因为地图每个点是一个小方块,所以只要是四边形,就一定是方形,而且没有三角形。
那要如何判断呢?
k=点四边是 # 的数量
每次联通时碰到新的点,角的数量就是这样的
if(k>1)
角的数量+=k-1;
只要最后角的数量大于4,就输出bad placement. 。
代码实现
最后看 AC code
#include<bits/stdc++.h>
#define int long long
#define itn int
using namespace std;
int n,m,ans=0;
int dx[4]={1,-1,0,0},dy[4]={0,0,-1,1};
char a[1005][1005];
void dfs(int x,int y)
{
a[x][y]='.';
for(int i=0;i<4;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<1 || xx>n || yy<1 || yy>m)
continue;
if(a[xx][yy]=='#')
dfs(xx,yy);
}
return ;
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int k=0;
if(a[i][j]=='#')
k++;
if(a[i+1][j]=='#')
k++;
if(a[i][j+1]=='#')
k++;
if(a[i+1][j+1]=='#')
k++;
if(k==3)
{
cout<<"Bad placement.\n";
return 0;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]=='#')
{
dfs(i,j);
ans++;
}
cout<<"There are "<<ans<<" ships.\n";
return 0;
}
本人是个蒟蒻,学艺不精,如有问题或建议请在评论区提出。
十分感谢!!!