宝石传递
解题思路
这是一个环形传递问题,N个生物围成一圈,每个生物i有两个属性:
-
s[i]:收到宝石后传递给下一个生物所需的时间 -
t[i]:上帝直接给该生物宝石的时间
我们需要计算每个生物第一次收到宝石的时间。关键点在于:
-
宝石可以通过两种方式到达:直接来自上帝,或者来自前一个生物
-
因为是环形结构,可能需要绕环多次才能确定最优解
代码注释
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, inf = 0x3f3f3f3f; // 定义常量,N为最大可能值+10,inf为无穷大
int n; // 生物数量
int dis[N]; // 存储每个生物第一次收到宝石的时间
int s[N], t[N]; // s[i]表示传递时间,t[i]表示直接接收时间
int main()
{
// 输入处理
cin >> n;
for(int i = 1; i <= n; i++) cin >> s[i]; // 输入每个生物的传递时间
for(int i = 1; i <= n; i++) {
cin >> t[i]; // 输入直接接收时间
dis[i] = t[i]; // 初始化dis数组,默认第一次接收时间就是直接接收时间
}
// 第一轮环形处理
dis[0] = t[n]; // 将第0位设为最后一个生物的值,方便环形处理
s[0] = s[n]; // 同上
t[0] = t[n]; // 同上
for(int i = 1; i <= n; i++) {
// 比较两种方式:直接接收 vs 从前一个生物传递过来
dis[i] = min(dis[i], dis[i - 1] + s[i - 1]);
}
// 第二轮环形处理(确保环形结构中的最优解能够完全传播)
dis[0] = dis[n]; // 更新第0位的值为处理后的最后一个生物的值
s[0] = s[n]; // 同上
t[0] = t[n]; // 同上
for(int i = 1; i <= n; i++) {
// 再次比较更新
dis[i] = min(dis[i], dis[i - 1] + s[i - 1]);
cout << dis[i] << endl; // 输出最终结果
}
return 0;
}
算法分析
-
初始化:每个生物的初始接收时间设为Takahashi直接给的时间
t[i] -
第一轮处理:
-
从第一个生物开始,比较"直接接收时间"和"前一个生物传递过来的时间"
-
更新每个生物的最早接收时间
-
-
第二轮处理:
-
因为环形结构,一轮处理可能不足以传播所有最优解
-
再次遍历确保最优解完全传播
-
-
输出结果:经过两轮处理后,
dis[i]即为每个生物第一次收到宝石的最早时间
为什么需要两轮处理?
考虑环形结构中,最优解可能需要绕环一周才能完全传播。例如:
-
生物1的最优解可能依赖于生物N的最优解
-
第一轮处理时,生物N的最优解可能还未计算完成
-
第二轮处理确保所有依赖关系都得到满足
时间复杂度
-
两轮线性遍历,时间复杂度为O(N)
-
完全满足题目中N≤200000的要求

浙公网安备 33010602011771号