题目简述
Farmer John一直努力让他的草地充满鲜美多汁的而又健康的牧草。可惜天不从人愿,他在植物大战人类中败下阵来。邪恶的乳草已经在他的农场的西北部份佔领了一片立足之地。
草地像往常一样,被分割成一个高度為Y(1 <= y <= 100), 宽度為X(1 <= x <= 100)的直角网格。(1,1)是左下角的格(也就是说坐标排布跟一般的X,Y坐标相同)。乳草一开始佔领了格(Mx,My)。每个星期,乳草传播到已被乳草佔领的格子四面八方的每一个没有很多石头的格(包括垂直与水平相邻的和对角线上相邻的格)。1周之后,这些新佔领的格又可以把乳草传播到更多的格裡面了。
Bessie想要在草地被乳草完全佔领之前尽可能的享用所有的牧草。她很好奇到底乳草要多久才能佔领整个草地。如果乳草在0时刻处於格(Mx,My),那麼还在那个时刻它们可以完全佔领入侵整片草地呢(对给定的数据总是会发生)?
草地由一个图片表示。"."表示草,而"*"表示大石。比如这个X=4, Y=3的例子。
....
..*.
.**.
如果乳草一开始在左下角(第1排,第1列),那麼草地的地图将会以如下态势发展:
.... .... MMM. MMMM MMMM
..*. MM*. MM*. MM*M MM*M
M**. M**. M**. M**. M**M
星期数 0 1 2 3 4
乳草会在4星期后佔领整片土地。
草地像往常一样,被分割成一个高度為Y(1 <= y <= 100), 宽度為X(1 <= x <= 100)的直角网格。(1,1)是左下角的格(也就是说坐标排布跟一般的X,Y坐标相同)。乳草一开始佔领了格(Mx,My)。每个星期,乳草传播到已被乳草佔领的格子四面八方的每一个没有很多石头的格(包括垂直与水平相邻的和对角线上相邻的格)。1周之后,这些新佔领的格又可以把乳草传播到更多的格裡面了。
Bessie想要在草地被乳草完全佔领之前尽可能的享用所有的牧草。她很好奇到底乳草要多久才能佔领整个草地。如果乳草在0时刻处於格(Mx,My),那麼还在那个时刻它们可以完全佔领入侵整片草地呢(对给定的数据总是会发生)?
草地由一个图片表示。"."表示草,而"*"表示大石。比如这个X=4, Y=3的例子。
....
..*.
.**.
如果乳草一开始在左下角(第1排,第1列),那麼草地的地图将会以如下态势发展:
.... .... MMM. MMMM MMMM
..*. MM*. MM*. MM*M MM*M
M**. M**. M**. M**. M**M
星期数 0 1 2 3 4
乳草会在4星期后佔领整片土地。
输入格式
* 第一行: 四个由空格隔开的整数: X, Y, Mx, My
* 第2到第Y+1行: 数据的第y+1行由X个字符("."表示草地,"*"表示大石),描述草地的
第(Y+2-y)行。
* 第2到第Y+1行: 数据的第y+1行由X个字符("."表示草地,"*"表示大石),描述草地的
第(Y+2-y)行。
输出格式
* 第一行: 一个单独的整数表示最后一个不是大石块的格子被乳草佔领的星期数。
测试样例1
输入
4 3 1 1
....
..*.
.**.
输出
4
#include <stdio.h>
struct note //定义队列结构体
{
int x; //当前的x坐标
int y; //当前的y坐标
int s; //拓展到当前位置的时间
};
int main()
{
struct note que[10002]; //草地最大为10000,队列拓展不超过10000
char a[101][101]; //定义二维数组存放地图
int next[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};//定义乳草的八个拓展方向
int head,tail; //队列头,队列尾
int i,j,k,n,m,tx,ty,book=0,q,p;
scanf("%d%d%d%d",&m,&n,&q,&p);
for(i=0;i<n;i++)
scanf("%s",a[i]); //读入地图
head=1;
tail=1; //初始队列
que[tail].x=q-1;
que[tail].y=n-p; //把起点放入队列开头
que[tail].s=0; //起点的时间为0
tail++; //队列长度加1
a[n-p][q-1]='M';
while(head<tail) //当队列长度不为0时
{
for(k=0;k<8;k++) //循环向八个不同方向拓展
{
tx=que[head].x+next[k][0];
ty=que[head].y+next[k][1]; //计算当前拓展位置的坐标
if(tx<0||tx>=m||ty>=n||ty<0) //判断当前坐标是否出界
continue;
if(a[ty][tx]=='.') //判断当前坐标是否为普通草
{
a[ty][tx]='M'; //将普通草变成乳草
que[tail].x=tx;
que[tail].y=ty; //将当前坐标加入到队列中
que[tail].s=que[head].s+1; //此位置的拓展时间是其父位置的拓展时间加1
tail++; //队列长度加1
}
book=0; //book标记变量
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(a[i][j]=='.') //此循环判断当前地图的普通草是否给感染完.
book=1; //一旦发现还有普通草就book=1,表示还需要继续拓展
if(book==0) //如果book=0表示所有草变成了乳草
break;
}
if(book==0)
break;
head++; //BFS重要的地方.拓展完的父坐标要丢掉.
}
printf("%d\n",que[tail-1].s); 输出时间
return 0;
}
以上代码有改进的地方:每次拓展后判断是否感染完可以换种思路判断,以上代码每次拓展完要遍历一遍地图耗时较大,可以改为输入地图时候记录普通草数量,每次感染数量减1.只需要判断普通草当前数量是否为0即可.
改进样例:
#include <stdio.h>
struct note
{
int x;
int y;
int s;
};
int main()
{
struct note que[10002];
char a[101][101];
int next[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
int head,tail;
int i,j,k,n,m,sum=0,tx,ty,q,p;
scanf("%d%d%d%d",&m,&n,&q,&p);
for(i=0;i<n;i++)
{
scanf("%s",a[i]);
for(j=0;j<m;j++)
if(a[i][j]=='.') //记录地图中普通草数量
sum++;
}
head=1;
tail=1;
que[tail].x=q-1;
que[tail].y=n-p;
que[tail].s=0;
tail++;
a[n-p][q-1]='M';
sum--; //读入起点后记得普通草数量减1
while(head<tail)
{
for(k=0;k<8;k++)
{
tx=que[head].x+next[k][0];
ty=que[head].y+next[k][1];
if(tx<0||tx>=m||ty>=n||ty<0)
continue;
if(a[ty][tx]=='.')
{
a[ty][tx]='M';
sum--; //每次成功拓展一个位置表示被感染一个,即普通草数量减1
que[tail].x=tx;
que[tail].y=ty;
que[tail].s=que[head].s+1;
tail++;
}
if(sum==0) //判断当前普通草数量是否为0
break;
}
if(sum==0)
break;
head++;
}
printf("%d\n",que[tail-1].s);
return 0;
}
一道简单的BFS应用的题目