题目链接: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. 出现 java.net.ConnectException: Connection refused 异常的原因及解决方法

    1 异常描述 在启动 Tomcat 服务器的时候,控制台一直输出异常信息,然后停止服务器,报出如下异常: 2 异常原因 通过观察上图中被标记出来的异常信息,咱们可以知道 java.net.Connec ...

  2. STS Eclipse IDEA 指定启动JDK版本

    使用场景: 开发人员在自己的机器上可能装了多个版本的JDK,但是在环境变量中只能配置一个 JAVA_HOME ,so你的IDEA Eclipse 可能因为你在 JAVA_HOME 配置JDK1.8 以 ...

  3. poj 1066 Treasure Hunt (Geometry + BFS)

    1066 -- Treasure Hunt 题意是,在一个金字塔中有一个宝藏,金字塔里面有很多的墙,要穿过墙壁才能进入到宝藏所在的地方.可是因为某些原因,只能在两个墙壁的交点连线的中点穿过墙壁.问最少 ...

  4. css实现简单的页面自适应宽度

    1.css样式.lgn{ width:500px; height:20px;}.item_left_yd{ float: left; display: inline-block; width:240p ...

  5. SpringMVC参数校验,包括JavaBean和基本类型的校验

    该示例项目使用SpringBoot,添加web和aop依赖. SpringMVC最常用的校验是对一个javaBean的校验,默认使用hibernate-validator校验框架.而网上对校验单个参数 ...

  6. .net Framework 源代码 · ScrollViewer

    本文是分析 .net Framework 源代码的系列,主要告诉大家微软做 ScrollViewer 的思路,分析很简单. 看完本文,可以学会如何写一个 ScrollViewer ,如何定义一个 IS ...

  7. [转]Redis哨兵模式(sentinel)学习总结及部署记录(主从复制、读写分离、主从切换)

    Redis的集群方案大致有三种:1)redis cluster集群方案:2)master/slave主从方案:3)哨兵模式来进行主从替换以及故障恢复. 一.sentinel哨兵模式介绍Sentinel ...

  8. 怎样在RxJS Observable中使用Async-Await

    怎样在RxJS Observable中使用Async-Await 一般情况下 async-await 和 Observables 并不能“在一起使用”.但RxJS 从一开始就具备与 Promises ...

  9. Html5 @media + css3 媒体查询

    css3 media媒体查询器用法总结   随着响应式设计模型的诞生,Web网站又要发生翻天腹地的改革浪潮,可能有些人会觉得在国内IE6用户居高不下的情况下,这些新的技术还不会广泛的蔓延下去,那你就错 ...

  10. H3C 衡量路由协议的主要指标