题目链接: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 题解 广度优先搜索的更多相关文章

  1. 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 ...

  2. 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 ...

  3. Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超级源点)

  4. Codeforces 1272E (Nearest Opposite Parity,反向建边)

    题意:给你n个数,每个数的值为a[i],每个点可以从i这号点跳转至(i - a[i]) 或 (i + a[i])点,点的范围为[1,n],然后问的是从偶数点跳至奇数点,从奇数点跳至偶数点的最少次数是多 ...

  5. 算法与数据结构基础 - 广度优先搜索(BFS)

    BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数 ...

  6. Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares)

    Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ar ...

  7. SDUT-2124_基于邻接矩阵的广度优先搜索遍历

    数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个无向连通图 ...

  8. 用一道模板题理解多源广度优先搜索(bfs)

    题目: //多元广度优先搜索(bfs)模板题详细注释题解(c++)class Solution { int cnt; //新鲜橘子个数 int dis[10][10]; //距离 int dir_x[ ...

  9. 图的广度优先搜索(BFS)

    把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...

随机推荐

  1. iptables 过滤条件(Matches)

    iptables可让你设置多种过滤条件,但是某些条件需要核心有提供相关功能才行.Iptables本身內建一般性的Internet Protocol (IP) 过滤条件,也就是說,即时沒载入任何扩充模组 ...

  2. PageHelper实现分页查询

    PageHelper是基于拦截器实现的myBatis分页插件 PageHelper的Github主页 : https://github.com/pagehelper/Mybatis-PageHelpe ...

  3. H3C 以太网流量控制

  4. CSS3 Box-shadow 阴影效果用法

    一.基本用法: 二.内阴影用法: 三.阴影扩展长度值: box-shadow: 4rpx 4rpx 8rpx #aaa;

  5. 【原生JS】评论编辑器 文本操作

    效果图: HTML: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> ...

  6. 前端开发工具之jQuery

    jQuery jQuery是一个轻量级的JavaScript第三方库,能够简单方便的进行JavaScript编程. jQuery选择器 1,id选择器: $("#id") 2,标签 ...

  7. HDU 6438"Buy and Resell"(贪心+优先级队列)

    传送门 •参考资料 [1]:HDU6438(优先队列+思维) •题意 有n个城市,第 i 天你会达到第 i 个城市: 在第 i 个城市中,你可以用 ai 元购买一个物品,或者用 ai 元卖掉一个物品, ...

  8. Vue 中的过滤器的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. P1082 数列分段

    题目描述 对于给定的一个长度为 \(N\) 的正整数数列 \(A_i\) ,现要将其分成连续的若干段,并且每段和不超过 \(M\) (可以等于 \(M\) ),问最少能将其分成多少段使得满足要求. 输 ...

  10. MySQL视图操作命令详解

    内容目录 创建视图 删除视图 修改视图 查看视图 §创建视图 在MySQL中,创建视图的完整语法如下: CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | ME ...