题解让我有点迷惑
  • 板块P1331 海战
  • 楼主饺子龙
  • 当前回复9
  • 已保存回复9
  • 发布时间2020/11/18 17:12
  • 上次更新2023/11/5 07:46:58
查看原帖
题解让我有点迷惑
131451
饺子龙楼主2020/11/18 17:12

在看题解的时候,感觉两篇排名较前的题解都有问题(也可能是我想错了?)

两篇题解的思路都是通过比较搜到的联通块面积和用它的长宽算出的面积是否一致。

@Violet9567

#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
using namespace std;
bool arr[1010][1010],vis[1010][1010];//arr数组是用来存图的,vis数组记录该位置是否访问过
int dirx[]={1,0,0,-1},k_s;//k_s是记录BFS已经遍历点的数量
int diry[]={0,1,-1,0},n,m,ans,lx,ly;//n,m是图的行数和列数,ans记录船的数量,lx和ly是记录起始点坐标
struct Node
{
    int x,y;//x是横坐标,y是纵坐标
};//声明结构体
int BFS_x(int x,int y)//计算矩形的长
{
    int k_x=0;
    for(;arr[x][y];++k_x,++x);
    return k_x;
}
int BFS_y(int x,int y)//计算矩形的宽
{
    int k_y=0;
    for(;arr[x][y];++k_y,++y);
    return k_y;
}
void BFS_fin(int x,int y)//BFS模板
{
    queue<struct Node>que;
    struct Node now;
    now.x = x, now.y = y;
    que.push(now),vis[x][y] = true;
    while(!que.empty())
    {
        now=que.front(),que.pop();
        for(int i=0;i<4;++i)
        {
            int xx = now.x + dirx[i],yy = now.y + diry[i];
            if(xx<lx||yy<ly)//特判
            {
                k_s=0;
                return;
            }
            if(xx < 1 || xx > n || yy < 1 || yy > m) continue;
            if(vis[xx][yy]) continue;
            if(!arr[xx][yy]) continue;
            struct Node next;
            next.x=xx;next.y=yy;
            k_s++;//联通块数量+1
            que.push(next),vis[xx][yy]=true;//标记访问过
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);//输入
    for(int i=1;i<=n;++i)
    {
        string s; cin>>s;
        for(int j=0;j<m;++j)
            if(s[j]=='#') arr[i][j+1]=1;//存图操作,‘#’为1,‘.’为0
    }
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)//枚举每一个点
        {
            if(!vis[i][j]&&arr[i][j])//如果没有访问过并且是‘#’
            {
                int x=BFS_x(i,j),y=BFS_y(i,j),s=0;//x,y分别代表矩形的长和宽,s是矩形的面积
                s=x*y,k_s=1;
                lx=i,ly=j;
                BFS_fin(i,j);//BFS遍历计算联通块面积
                if(s!=k_s)//如果面积不相等
                {
                    printf("Bad placement.\n"); return 0;//直接输出,退出程序
                }
                else ans++;//面积相等,船的数量+1
            }
        }
    }
    printf("There are %d ships.\n",ans);//输出船的数量
    return 0;
}

看完题解后发现好像向右特判的情况没有考虑到(类似下面这种)

3 4
###.
#.##
###.

然后在测试其代码的时候无意发现代码好像连样例都过不了?(但这位大佬本人是AC了的)

@221B

#include<bits/stdc++.h>//万能头
using namespace std;
char a[1005][1005];//用二维数组储存整个游戏棋盘
int n,m,s,k,q;
void dfs(int x,int y) {//x、y代表棋盘中一个点的坐标
	++q;//将每个“#”都累计起来
	a[x][y]='.';//避免重复,将找到的“#”变成“.”
	if(x-1>=1&&a[x-1][y]=='#')//向下查找与当前“#”所连接的“#”,注意x的值不能小于1,否则会超出整个数组
		dfs(x-1,y);
	if(x+1<=n&&a[x+1][y]=='#')//向上查找与当前“#”所连接的“#”,注意x的值不能大于n(即这一行的“.”与“#”的个数),否则同上
		dfs(x+1,y);
	if(y+1<=m&&a[x][y+1]=='#')//向右查找与当前“#”所连接的“#”,注意y的值不能超过m(即这一列的“.”与“#”的个数),否则...
		dfs(x,y+1);
	if(y-1>=1&&a[x][y-1]=='#')//向左查找与当前“#”所连接的“#”,注意y的值不能小于1
		dfs(x,y-1);
}
int main() {
	cin>>n>>m;//读入整个棋盘的行和列
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=m; j++)
		cin>>a[i][j];//输入整个棋盘
	}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++) {
			if(a[i][j]=='#') {//如果找到一个“#”,就代表这个地方有船
				q=0;//注意清零
				int h,l;
				h=l=0;//行的总数河北列的总数也要清零
				for(int x1=i; x1<=n; x1++) {//将这一列与当前“#”所连通的“#”的个数找出
					if(a[x1][j]=='#') {
						++l;
					} else break;
				}
				for(int x1=j; x1<=m; x1++) {//将这一行与当前“#”所连通的“#”的个数找出
					if(a[i][x1]=='#')
						++h;
					else break;
				}
				k=h*l;//将构成这艘船的“#”的个数算出(如果这艘船不与别的接触)
				dfs(i,j);//深搜走起
				if(q!=k)//诶?如果先前把这艘船当做矩形的“#”的个数与找出的“#”的个数不同
				{
				cout<<"Bad placement.";	//表示这艘船不为矩形
				return 0;//结束整个程序
				}
                ++s;//将这艘船计入
			}
		}
		cout<<"There are "<<s<<" ships.";//输出要规范哈
	return 0;//养成好习惯
}
  

这位大佬的代码是能AC的,但是好像也过不了上面那组数据?(会输出"There are 1 ships.")

萌新对洛谷题解的神圣不可侵犯的威严崩塌了,望有大佬来指点下迷津qwq

所以说一道普及-的题目我为什么搞出这么多屁事

2020/11/18 17:12
加载中...