175. 电路维修 双端队列广搜 类似堆优化dij的 双端队列(强行优先)BFS

这篇博客探讨了一种使用宽度优先搜索(BFS)算法来寻找网格中从起点到终点的最短路径的方法。当网格中的路径指示符遵循偶数步长规则时,该算法能够有效找到最小费用路径。在遇到特定地图标识时,算法优化了路径更新,形成小顶堆以提高效率。代码示例展示了如何实现这一过程,并在奇数点数的网格上进行了特判处理。
摘要由CSDN通过智能技术生成

题目

在这里插入图片描述
链接

题解思路

因为走的方向都是呈偶数形式的(对和的损耗),所以无法走到奇数的点。
可以进行特判。

记录这个点往四个方向的情况, 走的时候的标志以及地图的对应标志。
当符合地图标识的时候,就无需消耗权值,之间把他入队头。否则入队尾。
这样就强行形成了一个小顶堆。

有堆优化dij的味道了。

每次从队头取出元素来进行松弛操作。每个元素只能用来松弛其他边一次。

最后到n m 的最小费用就被搜索出来了。

AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
using namespace std;

const  int  INF =  0x3f3f3f3f;

int n , m ;

char mp[510][510] ;
bool st[510][510] ;
int vis[510][510] ;
int dx[4] = { -1 , -1 , 1 , 1 } ;
int dy[4] = { -1 , 1 , 1 , -1 } ;
char di[5] = "\\/\\/" ;
int xi[4] = { -1 , -1 , 0 , 0 } ;
int yi[4] = { -1 , 0  , 0 , -1 } ;

struct node
{
    int x , y ;
};

int bfs( )
{
    memset( st , 0 , sizeof(st) ) ;
    memset( vis , 0x3f , sizeof(vis) ) ;
    deque <node> q ;

    q.push_back({0,0}) ;
    vis[0][0] =  0;
    while ( !q.empty())
    {
        node tmp = q.front() ;
        q.pop_front() ;
     //   cout << tmp.x << " " << tmp.y << "\n" ;
        if ( tmp.x == n && tmp.y == m )
            return vis[n][m] ;
        if ( st[tmp.x][tmp.y] )
            continue ;
        st[tmp.x][tmp.y] = 1 ;
        for (int i = 0 ; i < 4 ; i++ )
        {
            int fx = tmp.x + dx[i] ;
            int fy = tmp.y + dy[i] ;
            int fxx = tmp.x + xi[i] ;
            int fyy = tmp.y + yi[i] ;
            if ( fx >= 0 && fy >= 0 && fx <= n && fy <= m )
            {
                 if ( mp[fxx][fyy] == di[i] )
                 {
                     if ( vis[fx][fy] > vis[tmp.x][tmp.y])
                     {
                        q.push_front({fx,fy});
                        vis[fx][fy] = vis[tmp.x][tmp.y] ;
                     }
                 }else
                 {
                     if ( vis[fx][fy] > vis[tmp.x][tmp.y] + 1 )
                     {
                        q.push_back({fx,fy});
                        vis[fx][fy] = vis[tmp.x][tmp.y] + 1 ;
                     }
                 }
            }
        }
    }
    return -1 ;
}



int main ()
{
    ios::sync_with_stdio(false);
    int T ;
    cin >> T ;
    while ( T -- )
    {
        cin >> n >> m ;
        for (int i = 0 ; i < n ; i++ )
            cin >> mp[i] ;
        if ( (n + m) % 2 )
            cout << "NO SOLUTION\n" ;
        else
        {
            cout << bfs() << "\n" ;
        }
    }

    return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值