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,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...
随机推荐
- Confluence 6 管理协同编辑 - 代理和 SSL 的考虑
对于你如何连接 Synchrony 是与你的环境有关的.我们知道绝大部分的 Confluence 站点是运行在反向代理后面的,同时还使用了 SSL.这里是帮助你在你环境中识别正确的配置的一些信息和一 ...
- MongoDB的简单操作
一.简介 二.MongoDB基础知识 三.安装 四.基本数据类型 五.增删改查操作 六.可视化工具 七.pymongo 一.简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库 MongoD ...
- 【gearman】gearmand -d 无反应解决
背景:安装了gearman后,用指令gearmand -d启动后.输入ps -ef|grep gearmand 查找不到.说明服务并没有启动. 查看报错: gearmand -d -l gear.lo ...
- 性能测试四十七:jmeter性能监控工具ServerAgent
在liunx压力机进行压测的时候,可以在widows下开一个jmeter,只进行监控用,不产生压力,监控效果和dstat差不多 jmeter安装客户端插件 把工具放到服务端任意目录并解压,我这里放到了 ...
- Jenkins构建后发送邮件
我们首先安装Jenkins邮件扩展插件“ Email Extension Plugin ”. Jenkins和插件的安装方法见上一篇文章:http://qicheng0211.blog.51cto.c ...
- fio 测试磁盘性能
在磁盘测试中最关心的几个指标分别为: iops(每秒执行的IO次数).bw(带宽,每秒的吞吐量).lat(每次IO操作的延迟). 当每次IO操作的block较小时,如512bytes/4k/8k等,测 ...
- 在CI框架中如何实现伪静态
第一步:在根目录下(index.PHP)同一级目录下建立一个.htaccess这个文件文件内容(即红色标识所显示的内容) URI 类 和 URL 辅助函数 包含了一些函数可以让你更容易的处理 URI ...
- java去除html代码中含有的html、js、css标签,获取文字内容
https://blog.csdn.net/u010882234/article/details/80585175
- [warn] 7#7: *676 a client request body is buffered to a temporary file /var/cache/nginx/client_temp/0000000007
nginx 上传文件遇到的Bug. fastcgi_buffer_size 128k; fastcgi_buffers 8 128k; fastcgi_busy_buffers_size 128k; ...
- php处理IOS图片旋转
$picAddr = $url; $exif = exif_read_data($picAddr); $image = imagecreatefromjpeg($picAddr); if($exif[ ...