题目背景
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了 F-2003 飞机。
此外,巡洋船只和舰队将被派去保护海岸线。不幸的是,因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们培养了一些新海军指挥官。军官们选择了“海战”游戏来帮助他们学习。
题目描述
在一个方形的盘上,放置了固定数量和形状的船只,每只船却不能碰到其它的船。在本题中,我们认为船是方形的,所有的船只都是由图形组成的方形。
求出该棋盘上放置的船只的总数。
输入格式
第一行为两个整数 R 和 C,用空格隔开,分别表示游戏棋盘的行数和列数。
接下来 R 行,每行 C 个字符,为
#
或.
。#
表示船只的一部分,.
表示水。
输出格式
一行一个字符串,如果船的位置放得正确(即棋盘上只存在相互之间不能接触的方形,如果两个
#
号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出There are S ships.
,S 表示船只的数量。否则输出Bad placement.
。
输入输出样例
输入
6 8 .....#.# ##.....# ##.....# .......# #......# #..#...#
输出
There are 5 ships.
说明/提示
对于 100% 的数据,1≤R,C≤1000。
思路:
此题本人也是读了好几遍和看样例才明白,根据题目要求,要求不能有船挨着和要求船是方
形组成的(这里的方形包括1*1的方形), 在2*2的方形中,下面这四种情况肯定是不满足的
# # . # 或 # # # . 或 # . # # 或 . # # #
所以这里就有一个方形 判断技巧如下:
此技巧记下来就好
//判断矩阵是不是方形小技巧 ,这里记下来就好
bool check(int x,int y)
{int cnt = 0;if(g[x][y] == '#') cnt++;if(g[x+1][y] == '#') cnt++;if(g[x][y+1] == '#') cnt++;if(g[x+1][y+1] == '#') cnt++;if(cnt == 3) return false;return true;
}
通过上面判断,接下来如果上面是true,那么此图就是合法的图,我们通过找最大连通块去找船即可
AC代码:
#include<iostream>
#include<cstring>using namespace std;const int N = 1010;
char g[N][N];
int r,c;//深搜去找多少个
void dfs(int x,int y)
{g[x][y] = '.';//找到'#',使其变成'.'//该点上下左右坐标偏移量 int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};for(int i=0;i<4;i++){int a = x + dx[i],b = y + dy[i];//满足情况就接着搜 if(a >= 1 && a<=r && b >= 1 && b<=c && g[a][b] == '#'){dfs(a,b);}}return;
} //判断矩阵是不是方形小技巧 ,这里记下来就好
bool check(int x,int y)
{int cnt = 0;if(g[x][y] == '#') cnt++;if(g[x+1][y] == '#') cnt++;if(g[x][y+1] == '#') cnt++;if(g[x+1][y+1] == '#') cnt++;if(cnt == 3) return false;return true;
}int main()
{cin >> r >> c;for(int i=1;i<=r;i++){for(int j=1;j<=c;j++){cin >> g[i][j];}}for(int i=1;i<=r;i++){for(int j=1;j<=c;j++){//不合法后面就不用找船的个数了 if(check(i,j) == false){printf("Bad placement.");return 0;}}}int ans = 0;for(int i=1;i<=r;i++){for(int j=1;j<=c;j++){if(g[i][j] == '#'){ans++;dfs(i,j); } }}printf("There are %d ships.",ans);return 0;
}