2601 电路维修 (双端队列bfs\优先队列bfs(最短路))
描述
Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上。Rika的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。
电路板的整体结构是一个R行C列的网格(R,C≤500),如右图所示。每个格点都是电线的接点,每个格子都包含一个电子元件。电子元件的主要部分是一个可旋转的、连接一条对角线上的两个接点的短电缆。在旋转之后,它就可以连接另一条对角线的两个接点。电路板左上角的接点接入直流电源,右下角的接点接入飞行车的发动装置。

Ha'nyu发现因为某些元件的方向不小心发生了改变,电路板可能处于断路的状态。她准备通过计算,旋转最少数量的元件,使电源与发动装置通过若干条短缆相连。不过,电路的规模实在是太大了,Ha'nyu并不擅长编程,希望你能够帮她解决这个问题。
输入格式
输入文件包含多组测试数据。第一行包含一个整数T 表示测试数据的数目。
对于每组测试数据,第一行包含正整数R 和C,表示电路板的行数和列数。
之后R 行,每行C 个字符,字符是"/"和"\"中的一个,表示标准件的方向。
输出格式
对于每组测试数据,在单独的一行输出一个正整数,表示所需的缩小旋转次数。
如果无论怎样都不能使得电源和发动机之间连通,输出NO SOLUTION。
样例输入
1
3 5
\\/\\
\\///
/\\\\
样例输出
1
数据范围与约定
- 对于40% 的数据,R,C≤5。
对于100% 的数据,R,C≤500,T≤5。
样例解释
样例的输入对应于题目描述中的情况。
只需要按照下面的方式旋转标准件,就可以使得电源和发动机之间连通。

思路:将网格交点当成点,然后就是从起点(1,1)到终点(r+1,c+1)的最短路径。
当前点与下一个点之间有线连接时,边权=0,没有时边权=1,
我们知道bfs要求队列的单调性和两段性,如果我们直接bfs,会导致有些总边权大的在边总权小的前面,单调性被破坏(单调性十分重要),那么我们肯定想到把边权小的往前面塞,边权大的往后面塞,这样就用到了双端队列。由于权值只会不变或者+1,序列一定维持两段性也就是直接往队列头加入和队列尾加入不会影响单调性。
另外,只有出队的时候的值才表示这个点的最短路径值(需要将所有当前边权的点跑一遍,将所有生成的下一个点按大小塞入队列,若一个点出现多次,队头取出的肯定最小) 。
这题由于权值只有0、1,导致了我们可以用双端队列控制其单调性,当然也可以直接用优先队列,用优先队列的话,基本就是堆优化的 Dijkstra
双端队列:
#include<bits/stdc++.h>
using namespace std; int t;
int r,c; char maps[][];
int vis[][];
int ways[][] = {,,-,-,-,,,-};
void init()
{
scanf("%d %d",&r,&c);
char s[];
for(int i=; i<=r; i++)
{
scanf("%s",s);
for(int j=; j<=c; j++)
{
maps[i][j] = s[j-];
}
}
} struct Node
{
int x,y;
Node(int x=,int y=):x(x),y(y) {}
}; bool check(int x,int y)
{
if(x < || x > r + || y < || y > c + )
return ;
return ;
} bool bfs()
{
deque<Node>que;
while(!que.empty())
que.pop_back();
que.push_back(Node(,));
memset(vis,0x3f,sizeof(vis));
vis[][] = ;
while(!que.empty())
{
Node tmp = que.front();
que.pop_front();
if(tmp.x == r+ && tmp.y == c+)return ;
for(int i=; i<; i++)
{
int xx = tmp.x + ways[i][];
int yy = tmp.y + ways[i][];
if(check(xx,yy))
{
char t = i <= ? '\\' : '/';
bool val = (maps[min(xx,tmp.x)][min(yy,tmp.y)] != t);
if(val + vis[tmp.x][tmp.y] < vis[xx][yy])
{
vis[xx][yy] = val + vis[tmp.x][tmp.y];
if(val)
que.push_back(Node(xx,yy));
else
que.push_front(Node(xx,yy));
}
}
}
}
return ;
} int main()
{ scanf("%d",&t);
while(t--)
{
init();
if(!bfs())
printf("NO SOLUTION\n");
else
printf("%d\n",vis[r+][c+]);
}
}
优先队列:
#include<bits/stdc++.h>
using namespace std; int r,c;
int t; char maps[][];
int vis[][];
int ways[][] = {,,-,-,-,,,-};
void init()
{
scanf("%d %d",&r,&c);
char s[];
for(int i=; i<=r; i++)
{
scanf("%s",maps[i]+);
}
}
struct Node
{
int val;
int x,y;
Node(int val,int x=,int y=):val(val),x(x),y(y) {}
}; bool operator<(const Node a,const Node b)
{
return a.val > b.val;
} bool check(int x,int y)
{
if(x < || x > r + || y < || y > c + )
return ;
return ;
} bool bfs()
{
priority_queue<Node,vector<Node> >que;
while(!que.empty())que.pop();
memset(vis,0x3f,sizeof(vis));
que.push(Node(,,));
que.push(Node(,,));
while(!que.empty())
{
Node tmp = que.top();
que.pop();
if(vis[tmp.x][tmp.y] != 0x3f3f3f3f)continue;
vis[tmp.x][tmp.y] = tmp.val;
if(tmp.x == r+ && tmp.y == c+)return ;
for(int i=;i<;i++)
{
int xx = tmp.x + ways[i][];
int yy = tmp.y + ways[i][];
if(!check(xx,yy))continue;
char t = i <= ? '\\' : '/';
bool val = maps[min(xx,tmp.x)][min(yy,tmp.y)] != t;
if(val + vis[tmp.x][tmp.y] < vis[xx][yy])
{
que.push(Node(val+vis[tmp.x][tmp.y],xx,yy));
}
}
}
return ;
} int main()
{
scanf("%d",&t);
while(t--)
{
init();
if(bfs())printf("%d\n",vis[r+][c+]);
else printf("NO SOLUTION\n");
}
}
2601 电路维修 (双端队列bfs\优先队列bfs(最短路))的更多相关文章
- CH 2601 - 电路维修 - [双端队列BFS]
题目链接:传送门 描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致 ...
- Luogu P2243 电路维修 双端队列BFS
当转移的代价是0和一个分明不同的权值时,可以用双端队列BFS去跑(你跑最短路也没问题..QWQ) 而对于这道题,边旋转代价是1,不旋转代价是0:可以直接建图最短路,也可以跑BFS 这个题建图很有意思: ...
- CH2601 电路维修(双端队列bfs)建图恶心
CH2601 电路维修 双端队列bfs,其实就是因为只有0和1所以可以直接2维护队列单调性(和优先队列一个道理) 建图的过程需要仔细斟酌(想一想id为什么这么写) 还有,空间要开够(很玄学),我一开始 ...
- POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】
<题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...
- POJ3662 SPFA//二分 + 双端队列最短路
https://cn.vjudge.net/problem/12427/origin 题意:求1到N第K + 1大条边权最小的路径 首先想到dp递推,dp[x][y]表示到x这个点经过y条免费边的最小 ...
- 电路维修 (广搜变形-双端队列bfs)
# 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...
- 电路维修(双端队列 & 最短路)
达达是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女翰翰,从而被收留在地球上. 翰翰的家里有一辆飞行车. 有一天飞行车的电路板突然出现了故障,导致无法启动. 电路板的整体结构是一个$ ...
- STL队列 之FIFO队列(queue)、优先队列(priority_queue)、双端队列(deque)
1.FIFO队列 std::queue就是普通意思上的FIFO队列在STL中的模版. 1.1主要的方法有: (1)T front():访问队列的对头元素,并不删除对头元素 (2)T back(): ...
- codeforces 1064D 双端队列BFS
双端队列BFS解决的就是路径权值可能为0的图最短路问题,权值为0插入队头,否则插入队尾. 对于这个题,可以看作上下移动的路径的权值为0,左右移动权值为1,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...
随机推荐
- Java 调用翻译软件实现英文文档翻译
前言: 因最近要进行OCP的考试准备.看着大堆英文文档确实有些疼痛.又因文档内容有点大,又需要逐一去翻译 又很费时费力.于是 百度了一番,找到一些 可以使用Java来调用百度翻译软件的API( 注:( ...
- Confluence 6 高级性能诊断
请在你的系统服务请求中包括下面所有的信息,如果可能的话,你也可以在请求中包括你认为最有可能出现的问题.这样的话,可以避免我们进一步对你系统的问题进行询问. 系统信息 Confluence 服务器 你系 ...
- 断路器Feign
Feign是自带断路器,需要在配置文件中开启断路器 改造消费者项目(FeignDemo) 1.在application.yml配置文件中开启断路器 eureka: client: service-ur ...
- BeautifulSoup的基本操作
>>> from bs4 import BeautifulSoup #导入 >>> soup = BeautifulSoup(url.content," ...
- Python基础之递归函数与二分法
一.递归函数 定义: 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 我们来举个例子吧,比如:有个人问“egon”年龄,他说比“小大”大5岁,“小大”又说比“小保 ...
- Kali安装问题解决方案
一.对今天安装Kalilinux 失败的原因做一个简单的总结, 1.安装之前的电脑状况,电脑配置Windows7 64位旗舰版配置,虚拟版本是VMware Workstation Pro14 ver ...
- Android播放功能的实现
Android播放语言功能的实现 需要用到的类文件TextToSpeech,此类可以实现播放语言的功能 支持播放的语言1.英语 2.法语 3.德语 4.意语 5.西班牙语 1.实例化此类,添加上下文对 ...
- 论文阅读笔记八:SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation (IEEE2017)
原文链接:https://arxiv.org/pdf/1511.00561.pdf github(tensorflow):https://github.com/aizawan/segnet 基于Seg ...
- 如何使用Scrapy框架实现网络爬虫
现在用下面这个案例来演示如果爬取安居客上面深圳的租房信息,我们采取这样策略,首先爬取所有租房信息的链接地址,然后再根据爬取的地址获取我们所需要的页面信息.访问次数多了,会被重定向到输入验证码页面,这个 ...
- 爬虫(猫眼电影+校花网+github+今日头条+拉钩)
Requests+正则表达式爬取猫眼TOP100榜电影信息 MARK:将信息写入文件解决乱码方法,开启进程池秒爬. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...