Luogu2243电路维修

Posted shiina-rikka

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu2243电路维修相关的知识,希望对你有一定的参考价值。

Luogu2243电路维修

传送门

原题

找到左上角到右下角的通路。可以旋转某一个方块,代价为一。
技术图片
lyd书上的例题2333

怎么做

将这个问题转化为从左上到右下的最短路问题。若这个角需要旋转则是权值为1的路径,否则权值为0。这个时候跑最短路就可以了。
由于路径的权值很特殊,我们可以考虑使用双端队列优化。当权值为0时从队头插入,权值为1时从队尾插入。每次取队头,这样就可以保证一直在走最优解。而不需要dijkstra堆优化或者SPFA多次寻找最优解。

码代码时还有优化注释在代码里了。

扔代码

#include <bits/stdc++.h>
using namespace std;
namespace sss

const int MAXN = 505;
int r, c;
//下一步的方向,减少码量
const int step_x[] = 1, -1, 1, -1;
const int step_y[] = 1, -1, -1, 1;
char s[MAXN][MAXN];
int d[MAXN][MAXN];
bool v[MAXN][MAXN];
struct node

    int x, y;
    node() 
    node(const int &_x, const int &_y)
    
        x = _x, y = _y;
    
;
//下一个点
inline node nextpoint(const node &now, const int &sp)

    return node(now.x + step_x[sp], now.y + step_y[sp]);

//路径对应的电线
inline node queryline(const node &now, const node &nxt)

    return node(max(now.x, nxt.x), max(now.y, nxt.y));

//判断是否合法
inline bool judge(const node &now, const int &sp)

    return now.x >= 0 && now.y >= 0 && now.x <= r && now.y <= c;

//bfs找最优解
inline void bfs()

    //多测不清空,爆零两行泪
    memset(d, 0x3f, sizeof(d));
    memset(v, 0, sizeof(v));
    deque<node> q;
    d[0][0] = 0;
    q.push_back(node(0, 0));
    while (q.size())
    
        node now = q.front();
        q.pop_front();
        if (v[now.x][now.y])
            continue;
        v[now.x][now.y] = true;
        //四次循环找下一个位置,不用手写四次
        for (register int sp = 0; sp <= 3; ++sp)
        
            //下一个点
            node nxt = nextpoint(now, sp);
            //对应的电线
            node lin = queryline(now, nxt);
            //合法才走
            if (judge(nxt, sp))
            
                //这个位置使用位运算进行优化。
                int z = (s[lin.x][lin.y] == '\\') ^ (sp == 0 || sp == 1);
                if (d[nxt.x][nxt.y] > d[now.x][now.y] + z)
                
                    d[nxt.x][nxt.y] = d[now.x][now.y] + z;
                    //三目运算符减少码量(懒)
                    z ? q.push_back(nxt) : q.push_front(nxt);
                
            
        
    

inline void sov()

    //多测不清空,爆零两行泪
    memset(s, 0, sizeof(s));
    scanf("%d %d", &r, &c);
    for (register int i = 1; i <= r; ++i)
        scanf("%s", s[i] + 1);
    bfs();
    //三目运算符减少码量(懒)
    d[r][c] == 0x3f3f3f3f ? (printf("NO SOLUTION\n")) : (printf("%d\n", d[r][c]));

 // namespace sss
int main()

    int T;
    scanf("%d", &T);
    for (register int ttt = 1; ttt <= T; ++ttt)
    
        sss::sov();
    

以上是关于Luogu2243电路维修的主要内容,如果未能解决你的问题,请参考以下文章

Luogu_P2243 电路维修题解 双端队列bfs

洛谷P2243 电路维修

洛谷 P2243 电路维修

P2243 电路维修

洛谷 2243Dijkstra

电路维修