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;
}

 

 

posted @ 2020-10-09 15:58  neverstopcoding  阅读(518)  评论(0编辑  收藏  举报