不同权值的bfs问题

不同权值的bfs问题

题目链接

解题思路:
多权bfs可以用优先队列优化以保证每一步都队列中取出的每一步都是最优解,但本题飞机和步行两种方式,先选飞行再选步行可以保证每步采取最优情况。
首先分析状态,可开三维vis数组,vis[x][y][kepp]表示走到(x,y)坐标可以继续续航keep时间所走的步数,由于降落后便可以是空地所以可以贪心飞行。
注意:搜索起点可能无法起飞,搜索终点无法降落等各种踩坑问题。
详解:代码注释

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 200+5;
const int INF = 0x3f3f3f3f;
struct Node{
    int x,y,keep;
    Node(){};
    Node(int xx,int yy,int kk):x(xx),y(yy),keep(kk){};
};

char maze[maxn][maxn];
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int vis[maxn][maxn][105];
//vis[x][y][kepp]走到(x,y)坐标可以继续续航keep时间所走的步数
int n,m,k,sx,sy,ex,ey;

inline bool judge(int &a,int b){
    if(a>b){
        a = b;
        return true;
    }
    return false;
}

void bfs(){
    --sx,--sy,--ex,--ey;
    memset(vis,0x3f,sizeof(vis));
    queue<Node>q;
    q.emplace(sx,sy,0);
    vis[sx][sy][0] = 0;
    while(!q.empty()){
        Node cur = q.front(); q.pop();
        int step = vis[cur.x][cur.y][cur.keep];
        for(int i=0;i<4;++i){
            int nx = cur.x + dir[i][0];
            int ny = cur.y + dir[i][1];
            if(nx<0||nx>=n||ny<0||ny>=m) continue;
            if(maze[cur.x][cur.y]=='.'){
                //k==1&&maze[nx][ny]=='.'
                //降落后立即起飞贪心飞行
                if((k==1&&maze[nx][ny]=='.')||k>1){
                    if(judge(vis[nx][ny][k-1],step+1)){
                        q.emplace(nx,ny,k-1);
                    }
                }
                if(judge(vis[nx][ny][0],step+2)){
                    q.emplace(nx,ny,0);
                }
            }
            else if(maze[cur.x][cur.y]=='#'){
                //下一个是空地继续降落后立即起飞贪心飞行
                if((cur.keep==1&&maze[nx][ny]=='.')||cur.keep>1){
                    if(judge(vis[nx][ny][cur.keep-1],step+1)){
                        q.emplace(nx,ny,cur.keep-1);
                    }
                }
            }
            else if(maze[cur.x][cur.y]=='x'){
                if((cur.keep==1&&maze[nx][ny]=='.')||cur.keep>1){
                    if(judge(vis[nx][ny][cur.keep-1],step+1)){
                        q.emplace(nx,ny,cur.keep-1);
                    }
                }
                else if(cur.keep==0&&maze[nx][ny]!='#'){
                    if(judge(vis[nx][ny][0],step+2)){
                        q.emplace(nx,ny,0);
                    }
                }
            }
        }
    }
    int ans = vis[ex][ey][0]; //ans初始为vis[ex][ey][0]
    //终点可能无法降落,需要提前找地方降落然后走过去
    if(maze[ex][ey]=='.'){
        for(int i=0;i<=k;++i){
            ans = min(ans,vis[ex][ey][i]);
        }
    }
    printf("%d\n",(ans!=INF)?ans:-1);
}

int main(){
    while(~scanf("%d%d%d",&n,&m,&k)){
        for(int i=0;i<n;++i){
            scanf("%s",maze[i]);
        }
        scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
        bfs();
    }
    return 0;
}`



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值