题目连接:http://codeforces.com/contest/1272/problem/Ec++
题目大意:
有一个长度为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\) 的点,……(你们能够本身画图体会一下,此时的广度优先搜索就是一个层次遍历)数组
而后咱们来看怎么使用广度优先搜索解决这个问题。spa
首先对于 \(a[i]\) 来讲,code
而后就能够开始咱们的搜索了。
在搜索以前咱们须要先开两个数组:队列
咱们先来求 \(odd\) 值,
咱们从 \(1\) 到 \(n\) 遍历 \(i\) ,ci
接下来每次从队列里面取出一个坐标 \(u\),而后遍历全部 \(u\) 能够到达的点 \(v\) ,若是 \(odd[v] > odd[u]+1\) ,则标记 \(odd[v] = odd[u]+1\) ,同时将 \(v\) 加入队列。get
最终每一个点的 \(odd\) 值即表示从坐标 \(i\) 出发最少须要花费多少步可以到达一个奇数值得点。it
而后咱们再来求 \(even\) 值(其实大家会发现是同样的道理),
咱们从 \(1\) 到 \(n\) 遍历 \(i\) ,class
接下来每次从队列里面取出一个坐标 \(u\),而后遍历全部 \(u\) 能够到达的点 \(v\) ,若是 \(odd[v] > odd[u]+1\) ,则标记 \(odd[v] = odd[u]+1\) ,同时将 \(v\) 加入队列。
自此,咱们就求解完了 \(odd\) 和 \(even\) 值。
而后咱们从 \(1\) 到 \(n\) 遍历坐标 \(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; }