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][maxn];
char s[maxn][maxn];
vector<pair<pair<int,int>, int> > p[maxn][maxn];
deque<pair<int,int> > q;
inline void add(int xx,int yy,int x,int y,int z){
    p[xx][yy].push_back(make_pair(make_pair(x,y), z));
}
inline void work(){
    scanf("%d%d",&r,&c);
    for(int i=1;i<=r;i++) scanf("%s",s[i]+1);
    for(int i=0;i<=r;i++)
        for(int j=0;j<=c;j++)
            p[i][j].clear();
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
            if(s[i][j]==‘/‘){
                add(i-1,j-1,i,j,1);
                add(i,j,i-1,j-1,1);
                add(i,j-1,i-1,j,0);
                add(i-1,j,i,j-1,0);
            }else{
                add(i-1,j-1,i,j,0);
                add(i,j,i-1,j-1,0);
                add(i,j-1,i-1,j,1);
                add(i-1,j,i,j-1,1);
            }
    memset(dis,0x3f,sizeof(dis));
    dis[0][0]=0;
    memset(vis,0,sizeof(vis));
    q.clear();
    q.push_back(make_pair(0,0));
    while(q.size()){
        int x=q.front().first,y=q.front().second;
        q.pop_front();
        vis[x][y]=1;
        if(x==r&&y==c){
            printf("%d\n",dis[r][c]);
            return;
        }
        for(int i=0;i<p[x][y].size();i++){
            int xx=p[x][y][i].first.first;
            int yy=p[x][y][i].first.second;
            int z=p[x][y][i].second;
            if(vis[xx][yy]) continue;
            if(dis[xx][yy]>dis[x][y]+z){
                dis[xx][yy]=dis[x][y]+z;
                if(z)
                    q.push_back(make_pair(xx,yy));
                else
                    q.push_front(make_pair(xx,yy));
            }
        }
    }
    printf("NO SOLUTION\n");
    return;
}

signed main()
{
    scanf("%d",&T);
    while(T--) work();
    system("pause");
    return 0;
}

原文地址:https://www.cnblogs.com/ChrisKKK/p/11460462.html

时间: 2024-08-03 04:33:56

Luogu_P2243 电路维修【题解】 双端队列bfs的相关文章

codeforces 1064D 双端队列BFS

双端队列BFS解决的就是路径权值可能为0的图最短路问题,权值为0插入队头,否则插入队尾. 对于这个题,可以看作上下移动的路径的权值为0,左右移动权值为1,而且不能超过规定的步数. 直接广搜求覆盖的点的数目即可. (场上我一般BFS被hack了) 代码: #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include

【BZOJ2457】[BeiJing2011]双端队列 贪心+模拟

[BZOJ2457][BeiJing2011]双端队列 Description Sherry现在碰到了一个棘手的问题,有N个整数需要排序. Sherry手头能用的工具就是若干个双端队列. 她需要依次处理这N个数,对于每个数,Sherry能做以下两件事: 1.新建一个双端队列,并将当前数作为这个队列中的唯一的数: 2.将当前数放入已有的队列的头之前或者尾之后. 对所有的数处理完成之后,Sherry将这些队列排序后就可以得到一个非降的序列. Input 第一行包含一个整数N,表示整数的个数.接下来的

BZOJ2457 [BeiJing2011]双端队列 【贪心】

题目 Sherry现在碰到了一个棘手的问题,有N个整数需要排序. Sherry手头能用的工具就是若干个双端队列. 她需要依次处理这N个数,对于每个数,Sherry能做以下两件事: 1.新建一个双端队列,并将当前数作为这个队列中的唯一的数: 2.将当前数放入已有的队列的头之前或者尾之后. 对所有的数处理完成之后,Sherry将这些队列排序后就可以得到一个非降的序列. 输入格式 第一行包含一个整数N,表示整数的个数.接下来的N行每行包含一个整数Di,其中Di表示所需处理的整数. 输出格式 其中只包含

8、泛型程序设计与c++标准模板库2.3双端队列容器

双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为<deque>. 1)双端队列容器的构造函数 有4中形式的构造函数: deque();//构造size()为0的双端队列容器 deque(size_type n,const T& v=T());//初始化大小为n的双端队列,第二个参数是每个元素的初始值,默认为T()构造的对象 deque(c

习题3.26双端队列

#include<stdio.h> #include<stdlib.h> struct Node; struct Queue; typedef struct Node * PtrToNode; typedef struct Queue * PtrToQ; struct Node{ PtrToNode Pre; PtrToNode Next; ElemenType Ele; } struct Queue{ PtrToNode front; PtrToNode rear; }; Ptr

nyoj1117 鸡蛋队列 (双端队列,deque)

题目1117 题目信息 运行结果 本题排行 讨论区 鸡蛋队列 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 将两根筷子平行的放在一起,就构成了一个队列.将带有编号的鸡蛋放到两根筷子之间叫做入队(push),将筷子之间的鸡蛋拿出来叫做出队(pop).但这两种方式有特殊的定义,对于入队,只能将鸡蛋从队列的尾部向里放入:对于出队,只能将鸡蛋从队列的头部向外将鸡蛋拿出来. 将①.②入队: 头____________尾                         ___

算法导论之八(10.1-5单数组实现双端队列)

算法导论第三版P131 题目: 10.1-5 栈插入和删除元素只能在同一端进行,队列的插入操作和删除操作分别在两端进行,与它们不同的,有一种双端队列(deque),其插入和删除操作都可以在两端进行.写出4个时间均为O(1)的过程,分别实现在双端队列插入和删除元素的操作,该队列使用一个数组实现的. 注意点: 1.左右端点指向的位置是类似于队列中的tail端点,是下一个插入操作的位置. 2.然后注意遍历的时候,左端点和右端点的位置关系,有两种可能,所以遍历的方式不一样. 代码: /* * 使用单数组

HDU 4286 Data Handler (双端队列)

Data Handler Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2455    Accepted Submission(s): 616 Problem Description You are in charge of data in a company, so you are called "Data Handler&qu

队列的应用:双端队列

双端队列(Deque:double ended queue)就是一个两端都是结尾的队列.队列的每一端都可以插入数据项和移除数据项.相对于普通队列,双端队列的入队和出队操作在两端都可进行. 双端队列的示意图: left:左端    right:右端 这里我们使用最常用的顺序结构来存储双端队列,为了节省空间,把它首尾相连,构成循环队列.并且规定left指向左端的第一个元素,right指向右端的下一个位置.那么队空的判断则是left==right,队满是(left-1+MAX)%MAX==right或