CF1272E. Nearest Opposite Parity 题解 广度优先搜索
题目链接:http://codeforces.com/contest/1272/problem/E
题目大意:
有一个长度为n的数组 \(a\) ,数组坐标从 \(1\) 到 \(n\) 。
假设你现在处于数组中的某一个位置,我们假设这个坐标为 \(i\) ,那么:
如果 \(1 <= i-a[i]\) ,那么你可以从坐标 \(i\) 移动到坐标 \(i-a[i]\) 位置(花费一步);
如果 \(i+a[i]<=n\) ,那么你可以从坐标 \(i\) 移动到坐标 \(i+a[i]\) 位置(同样花费一步)。
对于从 \(1\) 到 \(n\) 的所有坐标 \(i\) 来说,你想要的知道你最少需要几步可以从坐标 \(i\) 移动到一个坐标\(j\) ,
且 \(a[i]\) 和 \(a[j]\) 具有不同的奇偶性(也就是说,如果 \(a[i]\) 是偶数,那么 \(a[j]\) 就是奇数;如果 \(a[i]\) 是奇数,那么 \(a[j]\) 就得是偶数)。
解题思路:
这个问题可以转换成图论模型,然后用广度优先搜索或者最短路算法(Dijkstra或者SPFA算法)进行求解。
这里因为可能有些同学没有学到最短路算法,并且用最短路算法解决广搜可以解决的问题有一点杀鸡用牛刀的感觉(今年CSP-J复赛第4题可以用广搜做然而我也用了最短路SPFA算法),所以我这里还是讲解广度优先搜索解决这个问题。
对于一个边权均为 \(1\) 的图来说,我们通过广度优先搜索得到的就是最短路。因为此时一开始入队列的都是距起点 \(0\) 的点,然后入队列的是距起点 \(1\) 的点,然后入队列的是距起点 \(2\) 的点,……(大家可以自己画图体会一下,此时的广度优先搜索就是一个层次遍历)
然后我们来看怎么使用广度优先搜索解决这个问题。
首先对于 \(a[i]\) 来说,
- 如果 \(i-a[i] \ge 1\),则从 \(i-a[i]\) 向 \(i\) 连一条边;
- 如果 \(i+a[i] \le n\),则从 \(i+a[i]\) 向 \(i\) 连一条边。
然后就可以开始我们的搜索了。
在搜索之前我们需要先开两个数组:
- \(odd[i]\) 表示坐标为 \(i\) 的点到达最近的一个奇数点所需的最少步数;
- \(even[i]\) 表示坐标为 \(i\) 的点到达最近的一个偶数点所需的最少步数。
我们先来求 \(odd\) 值,
我们从 \(1\) 到 \(n\) 遍历 \(i\) ,
- 如果 \(a[i]\) 是奇数,则设 \(odd[i]\) 为 \(0\),同时将其加入队列;
- 否则(\(a[i]\) 为偶数),设 \(odd[i]\) 为无穷大。
接下来每次从队列里面取出一个坐标 \(u\),然后遍历所有 \(u\) 可以到达的点 \(v\) ,如果 \(odd[v] > odd[u]+1\) ,则标记 \(odd[v] = odd[u]+1\) ,同时将 \(v\) 加入队列。
最终每个点的 \(odd\) 值即表示从坐标 \(i\) 出发最少需要花费多少步能够到达一个奇数值得点。
然后我们再来求 \(even\) 值(其实你们会发现是一样的道理),
我们从 \(1\) 到 \(n\) 遍历 \(i\) ,
- 如果 \(a[i]\) 是偶数,则设 \(odd[i]\) 为 \(0\),同时将其加入队列;
- 否则(\(a[i]\) 为奇数),设 \(odd[i]\) 为无穷大。
接下来每次从队列里面取出一个坐标 \(u\),然后遍历所有 \(u\) 可以到达的点 \(v\) ,如果 \(odd[v] > odd[u]+1\) ,则标记 \(odd[v] = odd[u]+1\) ,同时将 \(v\) 加入队列。
自此,我们就求解完了 \(odd\) 和 \(even\) 值。
然后我们从 \(1\) 到 \(n\) 遍历坐标 \(i\),
- 如果 \(a[i]\) 是奇数,输出 \(even[i]\);
- 如果 \(a[i]\) 是偶数,输出 \(odd[i]\)。
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200020;
int n, a[maxn], odd[maxn], even[maxn];
vector<int> g[maxn];
queue<int> que;
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
for (int i = 1; i <= n; i ++) {
if (i-a[i] >= 1) g[ i-a[i] ].push_back(i);
if (i+a[i] <= n) g[ i+a[i] ].push_back(i);
}
// odd
for (int i = 1; i <= n; i ++) {
if (a[i]%2) {
odd[i] = 0;
que.push(i);
}
else odd[i] = -1;
}
while (!que.empty()) {
int u = que.front();
que.pop();
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i];
if (odd[v] == -1 || odd[v] > odd[u] + 1) {
odd[v] = odd[u] + 1;
que.push(v);
}
}
}
// even
for (int i = 1; i <= n; i ++) {
if (a[i] % 2 == 0) {
even[i] = 0;
que.push(i);
}
else even[i] = -1;
}
while (!que.empty()) {
int u = que.front();
que.pop();
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i];
if (even[v] == -1 || even[v] > even[u] + 1) {
even[v] = even[u] + 1;
que.push(v);
}
}
}
for (int i = 1; i <= n; i ++) {
if (i > 1) putchar(' ');
if (a[i] % 2) cout << even[i];
else cout << odd[i];
}
cout << endl;
return 0;
}
CF1272E. Nearest Opposite Parity 题解 广度优先搜索的更多相关文章
- Codeforces Round #605 (Div. 3) E. Nearest Opposite Parity(最短路)
链接: https://codeforces.com/contest/1272/problem/E 题意: You are given an array a consisting of n integ ...
- Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity
题目链接:http://codeforces.com/contest/1272/problem/E 题意:给定n,给定n个数a[i],对每个数输出d[i]. 对于每个i,可以移动到i+a[i]和i-a ...
- Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超级源点)
- Codeforces 1272E (Nearest Opposite Parity,反向建边)
题意:给你n个数,每个数的值为a[i],每个点可以从i这号点跳转至(i - a[i]) 或 (i + a[i])点,点的范围为[1,n],然后问的是从偶数点跳至奇数点,从奇数点跳至偶数点的最少次数是多 ...
- 算法与数据结构基础 - 广度优先搜索(BFS)
BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数 ...
- Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares)
Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ar ...
- SDUT-2124_基于邻接矩阵的广度优先搜索遍历
数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个无向连通图 ...
- 用一道模板题理解多源广度优先搜索(bfs)
题目: //多元广度优先搜索(bfs)模板题详细注释题解(c++)class Solution { int cnt; //新鲜橘子个数 int dis[10][10]; //距离 int dir_x[ ...
- 图的广度优先搜索(BFS)
把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...
随机推荐
- 用JavaScript判断网站是在手机端还是在PC端打开的方法
我们可以在网站的首页加上一段JavaScript代码对用户的浏览器进行判断,从而显示不同的网址,代码如下: <script type="text/javascript"> ...
- TAE words all
// vol 1 could do with sth rhinoplasty angst the wee small hours familial Munich gladi ...
- [kuangbin带你飞]专题九 连通图C - Critical Links UVA - 796
这道题就是要求桥的个数. 那么桥相应的也有判定的定理: 在和u相邻的节点中,存在一个节点是最小的时间戳都比 当前u的访问次序要大,也就是说这个点是只能通过果u到达,那么 他们之间相邻的边就是的桥 #i ...
- python中break和continue的区别
python中break和continue的区别 break和continue 1.break 意思为结束循环 例: i = 0 while i<10: i+=1 if ...
- H3C CSMA/CD载波侦听
- Python--day67--include包含其他的url和反向解析URL
1,include包含其他的url: 2,反向解析URL:
- 浅谈集合框架四——集合扩展:集合循环输出方式及list输出方式的效率对比
最近刚学完集合框架,想把自己的一些学习笔记与想法整理一下,所以本篇博客或许会有一些内容写的不严谨或者不正确,还请大神指出.初学者对于本篇博客只建议作为参考,欢迎留言共同学习. 之前有介绍集合框架的体系 ...
- 改善Azure App Service托管应用程序性能的几个技巧
本文介绍了几个技巧,这些技巧可以改善Azure App Service托管应用程序的性能.其中一些技巧是你现在就可以进行的配置变更, 而其他技巧则可能需要对应用程序进行一些重新设计和重构. 开发者都希 ...
- 一图理解vue生命周期
博客园上传图不太清晰,可以查看我的CSDN https://blog.csdn.net/jiaoshuaiai/article/details/90046736 感谢: https://segment ...
- linux 操作 I/O 端口
在驱动硬件请求了在它的活动中需要使用的 I/O 端口范围之后, 它必须读且/或写到这些 端口. 为此, 大部分硬件区别 8-位, 16-位, 和 32-位端口. 常常你无法混合它们, 象你 正常使 ...