双端队列bfs——电路维修

传送门:175. 电路维修 - AcWing题库

思路:首先要明确一点,只有在边权要么是0要么是1的图上才能使用双端队列bfs。

在题目的这个模型里面,要把每一个交叉点看做一个节点,起点就是(0,0),终点就是(n,m),与普通的二维迷宫图不同,这里扩展的方向不是普通的上下左右,而是左上,左下,右上,右下,而判断距离是0,还是1就要根据两点之间的斜线的形状是否是刚好连着两个点,是的话就是0,否则的话就是1,因为要靠旋转一次来达成连接的目的,对于输入的字符串图另外用一个图去存储,

如下图所示:每个格子里面就是斜线的编号,如果要判断节点(0,0)和节点(1,1)是否相连,就要看他们之间的(0,0)处的斜线是不是 \ 的形状,是的话(0,0)到(1,1)的距离为0,否则的话距离为1.

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<deque>
#define x first
#define y second
using namespace std;
typedef pair<int,int >PII;
const int N=510,M=N*N;
int dist[N][N];
char g[N][N];
bool st[N][N];
int n,m;
int bfs()
{
    memset(dist,0x3f,sizeof dist);
    memset(st,0,sizeof st);
    dist[0][0]=0;
    deque<PII>q;
    q.push_back({0,0});
    char cs[]="\\/\\/";//此处'\\'表示成一个‘\’
    int dx[4]={-1,-1,1,1};
    int dy[4]={-1,1,1,-1};
    int ix[4]={-1,-1,0,0};
    int iy[4]={-1,0,0,-1};
    while(q.size())
    {
        PII t=q.front();
        q.pop_front();
        if(st[t.first][t.second]) continue;
        st[t.first][t.second]=true;
        for(int i=0;i<4;i++)
        {
            int a=t.first+dx[i];
            int b=t.second+dy[i];
            if(a<0||a>n||b<0||b>m) continue;
            int ca=t.first+ix[i];
            int cb=t.second+iy[i];
            int d=dist[t.first][t.second]+(g[ca][cb]!=cs[i]);
            if(d<dist[a][b])
            {
                dist[a][b]=d;
                if(g[ca][cb]!=cs[i]) q.push_back({a,b});
                else q.push_front({a,b});
            }
        }
    }
return dist[n][m];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        scanf("%s",g[i]);
    int p=bfs();
    if(p==0x3f3f3f3f) puts("NO SOLUTION");
    else printf("%d\n",p);
}
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值