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,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...
随机推荐
- python之vscode配置开发调试环境
在vscode中下载python插件,下载量最多的就是 打开launch.json,把以下代码粘贴进去即可 { // 使用 IntelliSense 了解相关属性. // 悬停以查看现有属性的描述. ...
- 3790:最短路径问题(HDU)
Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Inp ...
- python selenium-webdriver 生成测试报告
测试最后的一个重要的过程就是生成一份完整的测试报告,生成测试报告的主要是通过python的一个第三方模块HTMLTestRunner.py生成,但是生成的测试报告不是特别的美观,而且没有办法统计测试结 ...
- NPOI操作Excel(二)--创建Excel并设置样式
由于XSSF中的XSSFWorkbook和HSSF中的HSSFWorkbook拥有的属性.方法等都是一样的,故下面就已一个为例做为展示,他们都继承与一个接口:IWorkbook(命名空间:using ...
- 论文阅读笔记二十一:MULTI-SCALE CONTEXT AGGREGATION BY DILATED CONVOLUTIONS(ICRL2016)
论文源址:https://arxiv.org/abs/1511.07122 tensorflow Github:https://github.com/ndrplz/dilation-tensorflo ...
- unicode解码
var newStr = System.Text.RegularExpressions.Regex.Unescape(str);
- 目标检测算法之YOLOv3
参考地址:https://blog.csdn.net/leviopku/article/details/82660381 YOLO v3结构图 DBL:卷积+BN+leaky relu,是v3的最小组 ...
- sqoop无法导出parquet文件到mysql
1.问题描述 在CDH集群中我们需要将Hive表的数据导入到RDBMS数据库中,使用Sqoop工具可以方便的将Hive表数据抽取到RDBMS数据库中,在使用Sqoop抽取Hive Parquet表时作 ...
- JQuery调用WCF服务
一:创建一个wcf服务项目 [ServiceContract] public interface IService1 { [OperationContract] [WebInvoke(RequestF ...
- 远程桌面管理工具Remote Desktop Connection Manager
使用说明:RDCMan安装好后双击打开RDCMan.exe,首次使用需要添加配置文件扩展名为rdg 1.点击File新建配置文件,这里命名为MRU,存放在安装的根路径下 建好之后,MRU会显示在左侧菜 ...