P1331 海战(洛谷)
题目描述
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机。此外,巡洋船只和舰队将被派去保护海岸线。不幸的是因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们考虑培养一些新的海军指挥官,他们选择了“海战”游戏来帮助学习。
在这个著名的游戏中,在一个方形的盘上放置了固定数量和形状的船只,每只船却不能碰到其它的船。在这个题中,我们仅考虑船是方形的,所有的船只都是由图形组成的方形。编写程序求出该棋盘上放置的船只的总数。
输入格式
输入文件头一行由用空格隔开的两个整数R和C组成,1<=R,C<=1000,这两个数分别表示游戏棋盘的行数和列数。接下来的R行每行包含C个字符,每个字符可以为“#”,也可为“.”,“#”表示船只的一部分,“.”表示水。
输出格式
为每一个段落输出一行解。如果船的位置放得正确(即棋盘上只存在相互之间不能接触的方形,如果两个“#”号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出一段话“There are S ships.”,S表示船只的数量。否则输出“Bad placement.”。
输入输出样例
6 8 .....#.# ##.....# ##.....# .......# #......# #..#...#
There are 5 ships.
题解思路:
这道题可以拿bfs和dfs进行解决(本题使用的是bfs),但题目的关键应该不是卡你会不会bfs或者dfs,难点在于如何去判断某个船体是否为“方形”。
判断船体是否为“方形”的方法:
法①:直接对输入的二维char型矩阵中去判断,每四个一组(不符合方形的情况都能归结到最终四种情况,因此以这个为基础去枚举判断),不符合就退出。判断结束后都符合是方形则再继续bfs
法②:结合bfs进行判断,通过面积来判断 因为刚好符合从上到下、从左到右的搜索,并且符合矩形的特点,若一个图形是矩形则它的起始搜索点(左上角的点)一定是最小的横纵坐标,所以只需要搜索图中的最大横纵坐标,对应相减再相乘求出矩形面积;另外,再搜索的过程中记录船体所占的数量(#数量);搜索结束后如果两者相等则代表当前船体满足方形要求。
解题代码:
#include<iostream> #include<queue> #include<algorithm> #include<string.h> using namespace std; int n,m; const int maxn=1000+5; char s[maxn][maxn]; //0的部分代表有水 int color[maxn][maxn]={0}; int sum=0; //记录船总数 typedef pair<int,int> P; int dx[4]={-1,0,1,0}; int dy[4]={0,-1,0,1}; //思路:在bfs中进行判断是否是矩形 int bfs(int x,int y){ //x y就是一个矩形的左上角坐标(当搜索的图是个标准矩形时) int maxx=x; //储存矩形最大x y int maxy=y; int num=0; //记录搜索的#数量 queue<P> que; P a; a.first=x; a.second=y; que.push(a); color[x][y]=2; //代表船体被使用过 num=1; while(!que.empty()){ P temp=que.front(); que.pop(); int xx=temp.first; int yy=temp.second; for(int i=0;i<4;i++){ //对4个方向进行搜索 int tx=xx+dx[i]; int ty=yy+dy[i]; //先判断是否越界 是否是船体部分 if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&color[tx][ty]==1){ if(tx>maxx){ maxx=tx; } if(ty>=maxy){ maxy=ty; } que.push(P(tx,ty)); //压入队列 color[tx][ty]=2; num++; } } } int area=(maxx-x+1)*(maxy-y+1); //求面积 if(area==num){ //代表是矩形 return true; }else return false; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>s[i][j]; if(s[i][j]=='#'){ color[i][j]=1; //1的部分代表是船体 2代表访问过的船体 } } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(color[i][j]==1){ if(bfs(i,j)){ sum++; }else{ cout<<"Bad placement."; //误触 return 0; } } } } cout<<"There are "<<sum<<" ships."; return 0; }