【海岛帝国系列赛】No.1 海岛帝国:诞辰之日

时间:2023-03-08 16:36:35
【海岛帝国系列赛】No.1 海岛帝国:诞辰之日

 50111117海岛帝国:诞辰之日

【试题描述】

YSF自从上次“被盗投降”完(带着一大堆债)回去以后,YSF对“海盗”怀念至今,他想要建立一个“药师傅”海岛帝国。

今天,他要像“管理部”那样去探寻一个新大陆!由于YSF得到了“郭同学”TONY.STARK的赞助。买了好多好多“旧手机”。

从而以某种不法行为GET航拍地图一张!YSF开着热气球,踏(jiu)上(zuo)了(qi)征(le)程(meng)。

YSF跳伞到了一个岛上,由于YSF素有幸运儿之称,所以幸运的他降落在了最大的小岛,但是,YSF一直想了解地图中别的岛,所以请你告诉天(tong)下(xin)闻(wei)名(min)而且还在做梦的YSF,地图上一共有几个小岛,最大的(YSF自己降落的小岛)小岛有多大?(温馨提示:数字表示海拔。0表示海洋,1~9都表示陆地。此处我们把YSF的跳伞点上下左右相连接陆地均视为同一岛屿,海拔不是面积!)

输入要求

* 第一行两个整数:n,m,分别表示地图的行和列。
* 接下来的n行m列为地图。

输出要求

* 共两行,第一行为小岛的个数N,输出:有N个小岛!
* 第二行为最大的小岛的面积M,输出:YSF降落的小岛面积有M!

输入实例


输出实例

有4个小岛!
YSF降落的小岛面积有38!

其它说明

地图的大小不超过50*50

试题分析

当时刚出过这样的一个乱搞而且把N个方法融合到一起的题,第一反应就是:打dfs+暴力+染色。这当然是最简单粗暴的方法。而且时间复杂度貌似不超啊~~~,所以就乱搞了这样的一个代码,每个点狂搜一遍,然后取最大值就可以求出ans2,但是,ans1怎么求呢?我们知道,目前只搜最大岛的面积函数只要两个参数,分别是x和y,表示YSF的坐标。而我们可以使用染色方法,对于每块走过的陆地染色。实现这个要求可以在我们的DFS函数里加上这样一个参数:color。原来的DFS如下:

 void dfs(int x,int y)
{
//定义一个方向数组
int next[][]={{,},//向右走
{,},//向下走
{,-},//向左走
{-,}};//向上走
int tx,ty,k;
//枚举前进方向
for(k=;k<=;k++)
{
//下一步后的坐标
tx=x+next[k][];
ty=y+next[k][];
if(tx< || tx>n || ty< || ty>m) continue;//边界判断、
//陆地判断
if(a[tx][ty]> && book[tx][ty]==)
{
sum++;//答案+1
book[tx][ty]=;//标记为已走过
dfs(tx,ty);//枚举下一个点
}
}
return ;
}

改进后的DFS只加了一行,可功能大大提升了

 void dfs(int x,int y,int color)
{
//定义一个方向数组
int next[][]={{,},//向右走
{,},//向下走
{,-},//向左走
{-,}};//向上走
int tx,ty,k;
a[x][y]=color;//对这个格子染色
//枚举前进方向
for(k=;k<=;k++)
{
//下一步后的坐标
tx=x+next[k][];
ty=y+next[k][];
if(tx< || tx>n || ty< || ty>m) continue;//边界判断、
//陆地判断
if(a[tx][ty]> && book[tx][ty]==)
{
sum++;//答案+1
book[tx][ty]=;//标记为已走过
dfs(tx,ty,color);//枚举下一个点
}
}
return ;
}

那么,既然染完色了,拿地图不就变成染色后的了吗?

想一想,有必要担心吗?

DFS1完全不会改变地图,只有DFS2会,我们先求DFS1,再求DFS2。

DFS1只会改变BOOK数组,而即使DFS1会改变地图,拿我们可以直接备份一个地图啊。

所以,可以放心的写代码了~~~

【代码】

 #include<iostream>
using namespace std;
int a[][];
int book[][],n,m,sum,ans=-,book2[][],sum1;
void dfs(int x,int y)
{
int next[][]={{,},
{,},
{,-},
{-,}};
int tx,ty,k;
for(k=;k<=;k++)
{
tx=x+next[k][];
ty=y+next[k][];
if(tx< || tx>n || ty< || ty>m) continue;
if(a[tx][ty]> && book[tx][ty]==)
{
sum++;
book[tx][ty]=;
dfs(tx,ty);
}
}
return ;
}
void dfs2(int x,int y,int color)
{
int next[][]={{,},
{,},
{,-},
{-,}};
int tx,ty,k;
a[x][y]=color;
for(k=;k<=;k++)
{
tx=x+next[k][];
ty=y+next[k][];
if(tx< || tx>n || ty< || ty>m) continue;
if(a[tx][ty]> && book2[tx][ty]==)
{
sum1++;
book2[tx][ty]=;
dfs2(tx,ty,color);
}
}
return ;
}
int main()
{
int startx,starty,num=;
cin>>n>>m;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
cin>>a[i][j];
for(startx=;startx<=n;startx++)
for(starty=;starty<=m;starty++)
{
book[startx][starty]=;
dfs(startx,starty);
book[startx][starty]=;
if(sum>ans) ans=sum;
sum=;
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(a[i][j]>)
{
num--;
book2[i][j]=;
dfs2(i,j,num);
}
printf("有%d个小岛!\nYSF降落的小岛面积有%d!\n",-num,ans);
}