题目背景
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了 F-2003 飞机。
此外,巡洋船只和舰队将被派去保护海岸线。不幸的是,因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们培养了一些新海军指挥官。军官们选择了“海战”游戏来帮助他们学习。
题目描述
在一个方形的盘上,放置了固定数量和形状的船只,每只船却不能碰到其它的船。在本题中,我们认为船是方形的,所有的船只都是由图形组成的方形。
求出该棋盘上放置的船只的总数。
输入格式
第一行为两个整数 R 和 C,用空格隔开,分别表示游戏棋盘的行数和列数。
接下来 R 行,每行 C个字符,为 # 或 . 。# 表示船只的一部分,. 表示水。
输出格式
一行一个字符串,如果船的位置放得正确(即棋盘上只存在相互之间不能接触的方形,如果两个 # 号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出 There are S ships. S表示船只的数量。否则输出 Bad placement.(注意,有句点!)。
样例输入 #1
6 8
.....#.#
##.....#
##.....#
.......#
#......#
#..#...#
样例输出 #1
There are 5 ships.
提示
对于 100% 的数据,1≤R,C≤1000。
思路
题目相信大家都看明白了吧,很显然,这是一个深度优先搜索题目哈,也就是说对于每一个“."(没有遍历过的)我们进行一次搜索,找到它的四连通块也就是船,定义cnt来统计船的数目,这个相信大家都知道,但此题的难点在于所谓的Bad placement.那么要如何判断Bad placement.呢?我们通过模拟可知对于每一个不合格的矩形,它一定有如下四种结构:
第一种 | ## #. |
第二种 | ## .# |
第三种 | .# ## |
第四种 | #. ## |
显而易见的,对于每一个2x2的不合法方块,都一定有3个#号和一个 . 号(可以理解吧)。
所以我们只需要在一次正式的搜索前面,对每一个2x2的方块进行一次搜索,判断是否有不合法方块,有的话直接输出 Bad placement. 代码结束,return 0;
否则进行下面的搜索,搜索还简单的吧,那么代码如下。
代码
/*对于一个不合法的方块,一定会有如下的状况
## ## .# #.
#. .# ## ##
也就是说对于一个2x2的方块一旦有3个#号和一个.号
*/
#include<iostream>
using namespace std;
const int N = 1005;
char x[N][N];
int a[N][N];
int vis[N][N];
int dir[4][2] = { {1,0},{-1,0},{0,-1},{0,1} };
int r, c;
int tmp = 0;
int cnt;
void dfs(int x, int y)
{
for (int i = 0; i < 4; i++)
{
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if (nx >= 1 && nx <= r && ny >= 1 && ny <= c && a[nx][ny] == 1 && vis[nx][ny] == 0)
{
tmp += 1;
vis[nx][ny] = tmp;
dfs(nx, ny);
}
}
return;
}
int main()
{
cin >> r >> c;
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
cin >> x[i][j];
if (x[i][j] == '#')
{
a[i][j] = 1;
}
if (x[i][j] == '.')
{
a[i][j] = 0;
}
}
}
int tmp_1 = 0,tmp_2=0;
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
if (a[i][j] == 1)
{
tmp_1++;
}
if (a[i][j+1] == 1)
{
tmp_1++;
}
if (a[i+1][j] == 1)
{
tmp_1++;
}
if (a[i+1][j+1] == 1)
{
tmp_1++;
}
if (a[i][j] == 0)
{
tmp_2++;
}
if (a[i][j + 1] == 0)
{
tmp_2++;
}
if (a[i + 1][j] == 0)
{
tmp_2++;
}
if (a[i + 1][j + 1] == 0)
{
tmp_2++;
}
if (tmp_2 == 1 && tmp_1 == 3)
{
cout << "Bad placement." << endl;
return 0;
}
tmp_1 = 0;
tmp_2 = 0;//初始化以便下次使用!
}
}
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
if (a[i][j] == 1 && vis[i][j] == 0)
{
dfs(i, j);
cnt++;
}
}
}
cout << "There are " << cnt << " ships.";
return 0;
}