版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
小Y上课摸鱼睡着了,梦里,他在一座岛上,因为是梦,所以他有上帝视角,他看到另一座岛上有宝藏,但是两座岛不相连,于是乎他现在要把一些海水变成路使得两座岛连通。由于小Y想省力,所以他会把尽量少的海水变成路,不过小Y作为一个计算机的学生,他已经做到看山不是山看水不是水,他现在眼中的岛是二位数组里的1,他眼中的水是二维数组里的0,那么刚才的问题就变成了,给你一个只包含01的二维数组,且岛是一个由1组成的四联通的块,0则是水,现在要求你把最少的0变成1,使得二维数组里有且仅有的两座相连。
输入
第一行一个个整数N表示二维数组有N行N列
接下来N行,每行N个数字0或1,0代表水,1代表岛
1<=N<=100
输出
一个整数表示最少的需要把0变成1的数量
输入样例
3
010
000
001
输出样例
2
dfs超时
最小步数用BFS。从岛2试探性的往外侧一格一格的扩张,首先找出所有1步可达的点,然后找出所有2步可达的点,依次类推。
具体实现:可以使用一个队列来保存所有的岛2的点,每次取出队列头部元素tmp,查看点tmp四周的四个点。遇到未标记的点就加到队列中,并标记该点成本为tmp对应成本+1,直到遇到岛1的点。
-----来自赵二狗对我问题的解答
#include<bits/stdc++.h>
using namespace std;
char g[110][110];
int n,minn=0x3f3f3f3f;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct node{
int x,y,t;
}p;
queue<node>q;
void pa(int x,int y)//将一块大陆用2标记
{
for(int i=0;i<4;i++)
{
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(g[tx][ty]=='1')
{
g[tx][ty]='2';
p.x=tx;p.y=ty;p.t=0;
q.push(p);
pa(tx,ty);
}
}
}
void bfs(int sx,int sy)//寻找最短路
{
int x,y,t;
while(!q.empty())
{
p=q.front();q.pop();
x=p.x;y=p.y;t=p.t;
for(int i=0;i<4;i++)
{
p.x=x+dir[i][0];
p.y=y+dir[i][1];
p.t=t+1;
if(p.x>=0&&p.x<n&&p.y>=0&&p.y<n&&g[p.x][p.y]!='2')
{
if(g[p.x][p.y]=='1')
{
cout<<t;return ;
}
g[p.x][p.y]='2';
q.push(p);
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++)
cin>>g[i];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
if(g[i][j]=='1')
{
g[i][j]='2';
p.x=i;p.y=j;p.t=0;
q.push(p);
pa(i,j);
bfs(i,j);
i=n;
break;
}
}
return 0;
}