题目链接: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. 20190608笔试题のCSS-属性继承

    以下的CSS属性哪些可以继承?(单选) A.   font-sizeB.   marginC.   widthD.   padding emmm,这题答案是A,看到这题我是能选对的,但又不由让我想到一 ...

  2. H3C 代理ARP

  3. CODE FESTIVAL 2017 qual A D Four Coloring(补题)

    这题看了好几天才看懂,一直误解题解中的d * d了 题解中说把大的格子划分成d * d的方格,我划分的时候把格子当作点来算的,一直觉得那明明是(d-1) * (d-1),昨天刚反映过来 思路:把格子旋 ...

  4. pip 将 某包指定到某目录 安装

    pip 将 某包指定到某目录  安装: pip install --target=d:\somewhere\other\than\the\default package_name

  5. H3C 常见ISDN连接方式

  6. Centos 6.5 配置hadoop2.7.1

    1 Centos 6.5 编译hadoop2.7.1 主机配置: sudo yum install gcc gcc-c++ sudo yum install ncurses-devel sudo yu ...

  7. Centos下添加用户到用户组

    将一个用户添加到用户组中,千万不能直接用: usermod -G groupA 这样做会使你离开其他用户组,仅仅做为 这个用户组 groupA 的成员. 应该用 加上 -a 选项: usermod - ...

  8. Educational Codeforces Round 5(A,B题)

    虽然是水题但还是贴下代码把 A #include<cstring> #include<cstdio> using namespace std; ; char x[qq],y[q ...

  9. java面向接口编程之适配器模式

    使用一个现成的类,但是它的接口不完全符合你的需求,我只想要它其中的一个方法,不想覆写其他的方法. 比如,窗体有变大,变小,关闭的行为,但是我现在只需要关闭行为;   package reviewDem ...

  10. tomcat最大线程数的设置

    Tomcat的server.xml中连接器设置如下 <Connector port="8080" maxThreads="150" minSpareThr ...