Sicily 1135 飞越原野 (SOJ 1135)「BFS 广度优先搜索」

0.00 avg. rating (0% score) - 0 votes
转载请注明: 吹水小镇 | reetsee.com
原文链接地址: http://blog.reetsee.com/archives/41

原题地址:点击打开链接

小时候看过这题,但是当时还小不会做,昨天晚上将其解决了。写省赛的总结(参见这里)花了不少时间,啊,所以堆到现在才来写。要吐个槽的是原本打算这周回家,以为在经过各种任务、面试洗礼后能够舒舒服服地和妹子回家看看钢铁侠1、2+复仇者联盟,没想到妹子星期6有广东移动的笔试要去,我也可能要在19号有另外一个面试·····哎,我想回家啊!

————————正文————————

此题其实和最正规的BFS差别不大,关键就是限制了有些地方不能走只能飞,有的地方可以走可以飞,所以在每个格子进行移动时,不但要考虑4个方向,还要考虑两种移动方式,考虑飞行的方式后,还要考虑其能飞多远。

由于题目的规模比较小,所以感觉最最暴力的做法都可以了,在每个格子既考虑飞也考虑走,然后每个格子同时记录使用时间最短的情况以及使用能量最少的情况,这样使用BFS的时候,如果搜到了终点,那么可以直接结束了。

这题的思路应该是非常清晰的,所以代码不长,大概80多行,但是看起来非常容易懂,就不多解释直接贴出来了,如下:

#include<iostream>
#include<stdio.h>
#include<queue>
#define INF 0x7fffffff
using namespace std;
int m,n,d;
bool f;
char c[105][105];
struct node
{
    int row,col,tt,dd; //行,列,到达节点的时间,到达节点花费的能量
}a[105][105][2]; //a[i][j][0]即i行j列耗时最少的节点,a[i][j][1]即i行j列耗能量最少的节点
queue<node> q;
void move(int rr, int cc, int tt, int dd)
{
  if(rr<0 || cc<0 || rr>=m || cc>=n || c[rr][cc]=='L')
     return;
  
  if(a[rr][cc][0].tt>tt || (a[rr][cc][0].tt==tt && a[rr][cc][0].dd>dd)) //如果时间更短,则更新
    {
        a[rr][cc][0].tt=tt;
        a[rr][cc][0].dd=dd; 
        q.push(a[rr][cc][0]);
    }
    if(a[rr][cc][1].dd>dd || (a[rr][cc][1].dd==dd && a[rr][cc][1].tt>tt)) //如果消耗能量更少,则更新
    {
        a[rr][cc][1].tt=tt;
		a[rr][cc][1].dd=dd;
        q.push(a[rr][cc][1]);
    }
    if(rr==m-1 && cc==n-1) //到达终点
     f=true;
}
bool bfs()
{
	while(!q.empty())
     q.pop();
    
	a[0][0][0].dd=a[0][0][0].tt=a[0][0][1].tt=a[0][0][1].dd=0;
    q.push(a[0][0][0]);
    q.push(a[0][0][1]);
    f=false;
    while(!q.empty() && !f)
    {
        node nn=q.front();
        q.pop();
		
		//不使用能量的情况下向4个方向行走
        move(nn.row-1,nn.col,nn.tt+1,nn.dd);
        move(nn.row+1,nn.col,nn.tt+1,nn.dd);
        move(nn.row,nn.col-1,nn.tt+1,nn.dd);
        move(nn.row,nn.col+1,nn.tt+1,nn.dd);
		
		//使用能量的情况下向4个方向飞行,这个循环可以优化
		for(int i=2;(d-i-nn.dd)>=0;i++)
		{
            move(nn.row-i,nn.col,nn.tt+1,i+nn.dd);
			move(nn.row+i,nn.col,nn.tt+1,i+nn.dd);
			move(nn.row,nn.col-i,nn.tt+1,i+nn.dd);
			move(nn.row,nn.col+i,nn.tt+1,i+nn.dd);
        }
    }
    return f;
}
int main()
{
    //freopen("in","r",stdin);
    //freopen("out","w",stdout);
    scanf("%d%d%d",&m,&n,&d);
    for(int i=0;i<m;++i)
     scanf("%s",&c[i]);
    if(m==1 && n==1)
    {
        printf("0\n");
        return 0;
    }
	for(int i=0;i<m;++i)
     for(int j=0;j<n;++j)
      for(int k=0;k<2;++k)
      {
         a[i][j][k].tt=a[i][j][k].dd=INF;
         a[i][j][k].row=i;
         a[i][j][k].col=j;
      }

    if(!bfs())
     printf("impossible\n");
    else
	 printf("%d\n",a[m-1][n-1][0].tt);
}

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注