[错题]电路维修

题目链接

WA代码

#include<bits/stdc++.h>
#define xx first
#define yy second
using namespace std;
typedef pair<int,int> pii;
const int N = 510;
string G[N];
int r,c;
int D[N][N];
const int d1[] = {-1,-1,1, 1}; // 点
const int d2[] = {-1, 1,1,-1};
const int k1[] = {-1,-1,0, 0}; // 边
const int k2[] = {-1, 0,0,-1};
const char kk[] = "\\/\\/";
int bfs(){
    deque<pii> q;
    memset(D,-1,sizeof D);
    q.push_back({0,0});
    D[0][0] = 0;
    while(!q.empty()){
        int x = q.front().xx,y = q.front().yy;
        q.pop_front();
        if(x == r and y == c) break;
        for(int i = 0;i < 4;i++){
            int dx = x + d1[i],dy = y + d2[i];
            int kx = x + k1[i],ky = y + k2[i];
            if(dx < 0 or dy < 0 or dx > r or dy > c) continue;
            if(~D[dx][dy]) continue;
            if(G[kx][ky] == kk[i]){
                D[dx][dy] = D[x][y];
                q.push_front({dx,dy});
            } 
            else{
                D[dx][dy] = D[x][y] + 1;
                q.push_back({dx,dy});
            }
        }
    }
    return D[r][c];
}

int main(){
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t; cin >> t;
    while(t--){
        cin >> r >> c;
        for(int i = 0;i < r;i++) cin >> G[i];
        cout << bfs() << endl;
    }
    return 0;
}

AC代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<deque>
#define xx first
#define yy second
using namespace std;
typedef pair<int,int> pii;
const int N = 510;
string G[N];
int r,c;
int D[N][N];
const int d1[] = {-1,-1,1, 1}; // 点
const int d2[] = {-1, 1,1,-1};
const int k1[] = {-1,-1,0, 0}; // 边
const int k2[] = {-1, 0,0,-1};
const char kk[] = "\\/\\/";
bool st[N][N]; 
int bfs(){
    if((r + c) % 2) return -1;
    deque<pii> q;
    memset(D,0x3f,sizeof D);
    memset(st,false,sizeof st);
    q.push_back({0,0});
    D[0][0] = 0;
    st[0][0] = true;
    while(!q.empty()){
        int x = q.front().xx,y = q.front().yy;
        q.pop_front();
        st[x][y] = true;
        if(x == r and y == c) break;
        for(int i = 0;i < 4;i++){
            int dx = x + d1[i],dy = y + d2[i];
            int kx = x + k1[i],ky = y + k2[i];
            if(dx < 0 or dy < 0 or dx > r or dy > c) continue;
            if(st[dx][dy]) continue;
            if(G[kx][ky] == kk[i] and D[dx][dy] > D[x][y]){
                D[dx][dy] = D[x][y];
                q.push_front({dx,dy});
            } 
            else if(G[kx][ky] != kk[i] and D[dx][dy] > D[x][y] + 1){
                D[dx][dy] = D[x][y] + 1;
                q.push_back({dx,dy});
            }
        }
    }
    return D[r][c];
}

int main(){
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t; cin >> t;
    while(t--){
        cin >> r >> c;
        for(int i = 0;i < r;i++) cin >> G[i];
        int res = bfs();
        if(~res) cout << res << endl;
        else cout << "NO SOLUTION" << endl;
    }
    return 0;
}

错误原因

错误原因是,误认为一个点第一次更新时的距离一定为最短距离。

这是一个假命题

因为在每一次从队列中取出一个点 ( x , y ) (x,y) (x,y)时,会更新其相邻的四个点的"距离"。
D [ d x ] [ d y ] = D [ x ] [ y ] + 1 D[dx][dy] =D[x][y] + 1 D[dx][dy]=D[x][y]+1时,仍然不能排除能够从另外一个距离为 D [ t x ] [ t y ] = D [ x ] [ y ] D[tx][ty] = D[x][y] D[tx][ty]=D[x][y]的点 ( t x , t y ) (tx,ty) (tx,ty),以 0 0 0的代价从 ( t x , t y ) (tx,ty) (tx,ty)走到 ( d x , d y ) (dx,dy) (dx,dy)

双端队列广搜,实际可以理解为dijkstra的简化版本。
我们每一次更新距离,即是一次松弛操作。
所以,我们可以仿照着,将初始距离设置为(理论上的)无穷大,然后在更新中使得最终取得的距离为最小距离。
因此,这里不能使用D数组作为是否需要更新该节点距离的判断依据,我们需要增加一个新的状态数组 s t st st

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wingaso

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值