首页 > 其他 > 详细

洛谷P1331 海战

时间:2019-08-05 23:13:36      阅读:268      评论:0      收藏:0      [点我收藏+]

此题源于洛谷P1331
链接奉上qwq:P1331
题目描述

在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机。此外,巡洋船只和舰队将被派去保护海岸线。不幸的是因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们考虑培养一些新的海军指挥官,他们选择了“海战”游戏来帮助学习。

在这个著名的游戏中,在一个方形的盘上放置了固定数量和形状的船只,每只船却不能碰到其它的船。在这个题中,我们仅考虑船是方形的,所有的船只都是由图形组成的方形。编写程序求出该棋盘上放置的船只的总数。

输入输出格式

输入格式:
输入文件头一行由用空格隔开的两个整数R和C组成,1<=R,C<=1000,这两个数分别表示游戏棋盘的行数和列数。接下来的R行每行包含C个字符,每个字符可以为“#”,也可为“.”,“#”表示船只的一部分,“.”表示水。

输出格式:
为每一个段落输出一行解。如果船的位置放得正确(即棋盘上只存在相互之间不能接触的方形,如果两个“#”号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出一段话“There are S ships.”,S表示船只的数量。否则输出“Bad placement.”。

输入输出样例

输入样例#1:

6 8
.....#.#
##.....#
##.....#
.......#
#......#
#..#...#

输出样例#1:

There are 5 ships.

这题是在模拟测试的时候做到的,因为我们班级的人很蒟蒻而且主要是普及的题目,所以这道题目是压轴题qwq
啊哈哈哈哈哈万分没想到的是我过了!我过了!

粗卡粗卡!!

【思路】
主要也要看自己的阅读能力吧......
注意这句话“我们仅考虑船是方形的,所有的船只都是由图形组成的方形”,说明一条船是由最大的#所组成的方形矩阵!
这道题我的想法也就是按照BFS入门题目的填涂颜色还有那个什么细胞分裂的想法一样的,算出连在一起的‘#‘的个数,而这个连在一起的个数就是最后船的个数。
但是这里要判断如果两艘船相邻,这个就比较恶心了,这个相邻的意思就是有两个方形矩阵相邻,且这两个方形无法组成新的方形。
比如下图就是一种例子:
技术分享图片
虽然这两个方形有部分相连,但是他们并不是同一个方形,所以这就是两个船,即第一个红方框围成的一个船,第二个红方框围成的一个船。
这里如果两个船相邻仅需要输出Bad placement.就可以了,这时候我们便可以使用一点点贪心(不是贪心算法的那个意思)
在BFS搜索的时候判断有没有以下情况,如果有的话那么就直接跳出搜索,直接输出Bad placement.
我们可以找一找规律,便可以发现如果两个#有以下情况:

  1. 技术分享图片
  2. 技术分享图片
    即如果两个#被一个或两个“.”夹着,那么这时候就说明这代表两个不同的方形了。
    (这里需要读者自己推敲)

【代码】

#include <stdio.h>
#include <string.h>

int dx[2][2]={{0,1},{1,0}}; //剪枝,不一定非要判断上下左右,只用判断右和下,因为左,下是已经判断过的,在判断一次就大大多了循环时间
int que[1000001][2],b[1001][1001],a[1001][1001],n,m,l;
/* que是队列,b是存储是否走过,a是存储原本的.#,
n,m是边界,l是判断是否有两个相邻的船,方便输出*/
int pd(int i,int j) //如思路所述的判断两个矩阵的
{
    if (a[i][j]==1)
            {
                if (a[i+1][j-1]==1)
                {
                    if (a[i+1][j]==0 || a[i][j-1]==0)
                    {
                        return 1;
                    }
                }
                    if (a[i+1][j+1]==1)
                    {
                        if (a[i+1][j]==0 || a[i][j+1]==0)
                        {
                            return 1;
                        }
                    }
                    if (a[i-1][j-1]==1)
                {
                    if (a[i][j-1]==0 || a[i-1][j]==0)
                    {
                        return 1;
                    }
                }
                if (a[i-1][j+1]==1)
                {
                    if (a[i-1][j]==0 || a[i][j+1]==0)
                    {
                        return 1;
                    }
                }
                }
                return 0;
            }
void BFS(int x,int y,int k) //BFS,这里的k可以省略,因为没什么用
{
    int tail=1,head=0,i,x1,y1;
    que[tail][0]=x;
    que[tail][1]=y; //源结点入队列
    b[x][y]=1; //标记判断过
    do
    {
        head++;
        for (i=0;i<2;i++)
        {
            x1=que[head][0]+dx[i][0]; 
            y1=que[head][1]+dx[i][1]; //扩展的坐标
            if (pd(x1,y1)==1)
            {
                l=1;
                return ;
            } //先判断旁边有没有别的船是相邻的,有的话就不用搜索了
            if (x1>=1 && x1<=n && y1>=1 && y1<=m && a[x1][y1]==1 && b[x1][y1]==0) //判断边界,判断走没走过,判断是不是#
            {
                tail++; 
                que[tail][0]=x1;
                que[tail][1]=y1; //拓展新的结点
                b[x1][y1]=1; //标记走过
                a[x1][y1]=k; //这里是为了辨别别的船,根据推敲,也不需要这一行,因为b数组的作用已经体现了,因此整个函数的int k也可以删去的
            }
            }
            
        }while (head<tail);
}
int main()
{

    char ch[10001];
    int total=0,i,j,k=1;
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
    {
        scanf("%s",ch); //输入的格式没有空格,因此需要先录入一个字符串
        for (j=0;j<=strlen(ch)-1;j++) //进行字符串存储到a数组里
        {
            if (ch[j]=='#')
            a[i][j+1]=1; //如果是船体的一部分#
            else //如果是海“.”
                a[i][j+1]=0;
        }
    }
    for (i=1;i<=n;i++)
    {
        for (j=1;j<=m;j++) //搜索
        {
            if (a[i][j]==1 && b[i][j]==0) //如果这个地方是船体,并且没有走过
            {
                k++; //可不要
                BFS(i,j,k); //进行循环,将这里这一片所连在一起的#进行标记判断
                total++; //船数量+1
            }
        }
    }
    if (l==1)
    {
        printf("Bad placement.\n");
    } //如果有船体相邻的
    else
    printf("There are %d ships.\n",total); //否则就输出船只数
    return 0;
}

【反思及注意点】
这道题考试的时候没有花太多的时间在标记船的部分,主要在推相邻船只那里用了点时间,可能不是最优的算法,所以希望大佬不要喷!

以上就是蒟蒻题解的全部内容啦!

洛谷P1331 海战

原文:https://www.cnblogs.com/CZPeng/p/11306040.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!