Saving Tang Monk II(BFS+priority-queue)

  •  
  • 从S点走到T点的最短路程,其中有氧气瓶分布在地图中,用'B'表示,它的作用是耗费2s穿过'#',每次穿过一个毒气室消耗一个氧气瓶,而氧气瓶最多能带5个,地图中还存在加速药丸,用'P'表示,可以有无限个,每使用一次可以节省1s的时间,但是无需带着加速药丸走只要遇到加速药丸不花时间通过即可,还有本题时间立的大顶堆时间多的优先出队。
  • #include<bits/stdc++.h>
    using namespace std;
    #define maxn 155
    int n,m,ans,sx,sy;
    char mmp[maxn][maxn];
    bool vis[10][maxn][maxn];
    bool judge(int x,int y)
    {
        if(x<0||y<0||x>n-1||y>m-1)
            return true;
        return false;
    }
    int to[5][2]= {{0,1},{0,-1},{1,0},{-1,0}};
    struct node
    {
        int x,y,sum,step;
        bool operator<(const node &a)const
        {
            if(a.step ==step)return a.sum < sum;
            return a.step < step;
        }
    } top,temp;
    void bfs(int x,int y)
    {
        priority_queue<node>q;
        q.push((node)
        {
            x,y,0,0
        });
        vis[0][x][y]=1;
        while(!q.empty())
        {
            top=q.top();
            q.pop();
            if(mmp[top.x][top.y]=='T')
            {
                cout<<top.step<<endl;
                return ;
            }
            for(int i=0; i<4; i++)
            {
                temp.x=top.x+to[i][0];
                temp.y=top.y+to[i][1];
    //            cout<<temp.x<<" "<<temp.y<<endl;
                if(judge(temp.x,temp.y))
                    continue;
    //            cout<<temp.x<<" "<<temp.y<<endl;
    //                cout<<endl<<temp.x<<" "<<temp.y<<endl;
                if(mmp[temp.x][temp.y]=='B')
                {
                    temp.sum=min(top.sum+1,5);
                    temp.step=top.step+1;
                    if(vis[temp.sum][temp.x][temp.y])
                        continue;
                    vis[temp.sum][temp.x][temp.y]=1;
                    q.push(temp);
                }
                else if(mmp[temp.x][temp.y]=='P')
                {
    //                cout<<temp.x<<" "<<temp.y<<endl;
                    temp.sum=top.sum;
                    temp.step=top.step;
                    if(vis[temp.sum][temp.x][temp.y])
                        continue;
                    vis[temp.sum][temp.x][temp.y]=1;
                    q.push(temp);
                }
                else if(mmp[temp.x][temp.y]=='.'||mmp[temp.x][temp.y]=='T'||mmp[temp.x][temp.y]=='S')
                {
                    temp.sum=top.sum;
                    temp.step=top.step+1;
                    if(vis[temp.sum][temp.x][temp.y])
                        continue;
                    vis[temp.sum][temp.x][temp.y]=1;
                    q.push(temp);
                }
                else if(mmp[temp.x][temp.y]=='#')
                {
                    temp.sum=top.sum-1;
                    temp.step=top.step+2;
                    if(temp.sum<0)continue;
                    if(vis[temp.sum][temp.x][temp.y])
                        continue;
                    vis[temp.sum][temp.x][temp.y]=1;
                    q.push(temp);
                }
            }
        }
    //    cout<<q.size()<<endl;
        cout<<-1<<endl;
        return ;
    }
    int main()
    {
        while(cin>>n>>m)
        {
            if(!n&&!m)
                break;
            memset(vis,0,sizeof(vis));
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                {
                    cin>>mmp[i][j];
                    if(mmp[i][j]=='S')
                    {
                        sx=i;
                        sy=j;
                    }
                }
            bfs(sx,sy);
        }
        return 0;
    }
    
  •  
  •  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值