CF1272E. Nearest Opposite Parity 题解 广度优先搜索
题目链接:http://codeforces.com/contest/1272/problem/E
题目大意:
有一个长度为n的数组 ,数组坐标从 到 。
假设你现在处于数组中的某一个位置,我们假设这个坐标为 ,那么:
如果 ,那么你可以从坐标 移动到坐标 位置(花费一步);
如果 ,那么你可以从坐标 移动到坐标 位置(同样花费一步)。
对于从 到 的所有坐标 来说,你想要的知道你最少需要几步可以从坐标 移动到一个坐标 ,
且 和 具有不同的奇偶性(也就是说,如果 是偶数,那么 就是奇数;如果 是奇数,那么 就得是偶数)。
解题思路:
这个问题可以转换成图论模型,然后用广度优先搜索或者最短路算法(Dijkstra或者SPFA算法)进行求解。
这里因为可能有些同学没有学到最短路算法,并且用最短路算法解决广搜可以解决的问题有一点杀鸡用牛刀的感觉(今年CSP-J复赛第4题可以用广搜做然而我也用了最短路SPFA算法),所以我这里还是讲解广度优先搜索解决这个问题。
对于一个边权均为 的图来说,我们通过广度优先搜索得到的就是最短路。因为此时一开始入队列的都是距起点 的点,然后入队列的是距起点 的点,然后入队列的是距起点 的点,……(大家可以自己画图体会一下,此时的广度优先搜索就是一个层次遍历)
然后我们来看怎么使用广度优先搜索解决这个问题。
首先对于 来说,
- 如果 ,则从 向 连一条边;
- 如果 ,则从 向 连一条边。
然后就可以开始我们的搜索了。
在搜索之前我们需要先开两个数组:
- 表示坐标为 的点到达最近的一个奇数点所需的最少步数;
- 表示坐标为 的点到达最近的一个偶数点所需的最少步数。
我们先来求 值,
我们从 到 遍历 ,
- 如果 是奇数,则设 为 ,同时将其加入队列;
- 否则( 为偶数),设 为无穷大。
接下来每次从队列里面取出一个坐标 ,然后遍历所有 可以到达的点 ,如果 ,则标记 ,同时将 加入队列。
最终每个点的 值即表示从坐标 出发最少需要花费多少步能够到达一个奇数值得点。
然后我们再来求 值(其实你们会发现是一样的道理),
我们从 到 遍历 ,
- 如果 是偶数,则设 为 ,同时将其加入队列;
- 否则( 为奇数),设 为无穷大。
接下来每次从队列里面取出一个坐标 ,然后遍历所有 可以到达的点 ,如果 ,则标记 ,同时将 加入队列。
自此,我们就求解完了 和 值。
然后我们从 到 遍历坐标 ,
- 如果 是奇数,输出 ;
- 如果 是偶数,输出 。
实现代码如下:
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人