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();
    }
}

原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11629327.html

时间: 2024-10-12 15:34:39

Luogu2243电路维修的相关文章

洛谷 P2243 电路维修

P2243 电路维修 题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和James,可是一直也没能给他们帮上什么忙. 题目描述 有一天 Mark 和James 的飞行车没有办法启动了,经过检查发现原来是电路板的故障.飞行车的电路板设计很奇葩,如下图所示: 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行包含一个整数T 表示测试数据的数目. 对于每组测试数据,第一行包

洛谷P2243 电路维修

P2243 电路维修 题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和James,可是一直也没能给他们帮上什么忙. 题目描述 有一天 Mark 和James 的飞行车没有办法启动了,经过检查发现原来是电路板的故障.飞行车的电路板设计很奇葩,如下图所示: 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行包含一个整数T 表示测试数据的数目. 对于每组测试数据,第一行包

luogu P2243 电路维修

P2243 电路维修 题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和James,可是一直也没能给他们帮上什么忙. 题目描述 有一天 Mark 和James 的飞行车没有办法启动了,经过检查发现原来是电路板的故障.飞行车的电路板设计很奇葩,如下图所示: 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行包含一个整数T 表示测试数据的数目. 对于每组测试数据,第一行包

电路维修

[题目描述]: 电路维修 [思路]: 开先看起来挺迷的,觉得没法做,搜索也写不出来... 再仔细分析题目,发现对于任意一根电路,它只有两种状态: 连着右上和坐下 连着左下和右上 要求最小的操作数. 我们可以发现,每条电线可以花费1的代价从一种状态改变为另外一种状态,那么我们可以对于已经连着的两点连一条权为0的边,没连着的连一条花费为1的边,求出从左上角到右下角的最短路即可. 注:卡\(SPFA\),建议用\(SLF\) \(or\) \(LLL\) \(or\) 堆优化的\(DJ\),此处用的\

【CH2601】电路维修

这是一道广搜题,难点在于对题目的理解和对细节的处理. 对于一个节点,可以向左上.左下.右上.右下四个位置扩展,根据地图的形态确定每一步扩展的代价. 将代价最小的节点放在队头,这样用双端队列来实现.每个节点最多进出队列一次,所以时间复杂度为O(r*c) 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace s

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

题面:https://www.luogu.org/problem/P2243 建边. 对角线有相连路的边权为0,没有的为1. 然后双端队列bfs求最短路. 将边权为0的到的点从队头入队. 边权为1到的点从队尾入队. 这样可以保证最优. 代码如下: #include<bits/stdc++.h> #define int long long using namespace std; const int maxn=510; int T,r,c,dis[maxn][maxn],vis[maxn][ma

算法提高课——搜索

BFS 求最小 基迭代,不会爆栈 Flood fill算法: 可以在线性时间复杂度内,找到某个点所在的连通块. //Home键到行首,End键到行尾 AcWing 1097. 池塘计数 AcWing 1098. 城堡问题 AcWing 1106. 山峰和山谷 最短路模型: 所有边权相等时,可以在线性时间内得到单源或多源最短路(可视为特殊的dijkstra) AcWing 1076. 迷宫问题 AcWing 188. 武士风度的牛 AcWing 1100. 抓住那头牛 AcWing 173. 矩阵

学习 研究 修理 ,维修, 电路, 家电

修理 ,维修, 电路, 家电 http://www.haohetao.com/thread-1024305-1-1.html wwbl ft0http://www.haohetao.com/thread-1024306-1-1.html wwbl ft1http://www.haohetao.com/thread-1024308-1-1.html wwbl ft2http://www.haohetao.com/thread-1024309-1-1.html wwbl ft3http://www.

维修电路

两个点,如果有线连接,则边权为0,否则边权为1 如果扩展到一个点,边权是0,则把这个点加入到队列的首端,因为对于权值来说,相当于没扩展 这就是双端队列,这里如果将将要加入的距离与队头的距离比较,会错??? 注意不能map[xx][yy]=='\',要map[xx][yy]=='\\' 这个代码是照蓝书抄的,这是一个很巧妙的办法,每个map中的x和y都是要比较的两个x和y中的较小值 而我之前写的把点编号的方法一定会MLE,更不必说直接上四维数组的了 还容易写错 1 #include<iostrea