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

26 篇文章 0 订阅
3 篇文章 0 订阅

原题地址:点击打开链接

小时候看过这题,但是当时还小不会做,昨天晚上将其解决了。写省赛的总结(参见这里)花了不少时间,啊,所以堆到现在才来写。要吐个槽的是原本打算这周回家,以为在经过各种任务、面试洗礼后能够舒舒服服地和妹子回家看看钢铁侠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);
}                                 



******<转载说明>******
转载注明:诚实的偷包贼
原文地址:http://blog.csdn.net/fanfank/article/details/8924029
******<转载说明/>******

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值