题解:洛谷 P4016 负载平衡问题
【题目来源】
【题目描述】
G 公司有 \(n\) 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等。如何用最少搬运量可以使 \(n\) 个仓库的库存数量相同。搬运货物时,只能在相邻的仓库之间搬运。
【输入】
第一行一个正整数 \(n\),表示有 \(n\) 个仓库。
第二行 \(n\) 个正整数,表示 \(n\) 个仓库的库存量。
【输出】
一行一个非负整数,输出最少搬运量。
【输入样例】
5
17 9 14 16 4
【输出样例】
11
【核心思想】
-
问题分析:给定 \(n\) 个环形排列的仓库,每个仓库存储 \(a_i\) 数量的货物,只能在相邻仓库之间搬运货物。求使所有仓库库存相同的最小搬运量。这是一个贪心 + 中位数问题,关键在于将环形问题转化为线性问题,并利用中位数性质最小化绝对值之和。
-
算法选择:
- 贪心传递:从第一个仓库开始,依次将每个仓库调整到平均值,将差额传递给下一个仓库
- 中位数优化:记录每个仓库的累计传递量,以中位数为基准计算最小搬运量
- 偏移量枚举:尝试正负偏移量,找到使总搬运量最小的基准点
-
关键步骤:
- 计算平均值:
avg = sum / n,即每个仓库最终应有的库存量 - 贪心传递(\(i = 1\) 到 \(n-1\)):
- 计算第 \(i\) 个仓库需要调整的数量:
t = avg - a[i] - 将第 \(i\) 个仓库调整为平均值:
a[i] = avg - 从下一个人处调整:
a[i + 1] -= t - 记录传递量:
b[i + 1] = t - 累加操作次数:
ans += abs(t)
- 计算第 \(i\) 个仓库需要调整的数量:
- 中位数优化:
- 以当前传递量为基础,尝试正偏移
calc(i)和负偏移calc(-i) - 当操作次数增加时停止,更新最小搬运量
- 以当前传递量为基础,尝试正偏移
- 输出
ans
- 计算平均值:
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),贪心传递 \(O(n)\),偏移量枚举 \(O(n)\)
- 空间复杂度:\(O(n)\),存储库存数组和传递记录数组
-
贪心传递与中位数的核心思想:
- 环形转线性:固定一个仓库为起点,将环形问题转化为线性传递问题
- 局部最优:每次将一个仓库调整到平均值,将差额传递给下一个仓库,保证局部最优
- 累计传递量:
b[i]表示第 \(i\) 个仓库从前面累计接收的货物量,以中位数为基准最小化sum(|b[i] + x|) - 中位数性质:使绝对值之和最小的点是中位数,通过枚举偏移量找到最优基准点
- 适用于环形均分、最小搬运量、负载平衡类问题
【算法标签】
普及+ #贪心
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int n, sum, ans; // n: 人数, sum: 糖果总数, ans: 最少操作次数
int a[N], b[N]; // a: 初始糖果数, b: 传递记录
// 计算偏移量为x时的操作次数
int calc(int x)
{
int res = 0;
for (int i = 1; i <= n; i++)
{
res += abs(b[i] + x); // 计算新的传递量
}
return res;
}
int main()
{
cin >> n; // 输入人数
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum += a[i]; // 计算总糖果数
}
int avg = sum / n; // 平均每人糖果数
// 贪心传递,使每个人达到平均数
for (int i = 1; i < n; i++)
{
int t = avg - a[i]; // 第i人需要调整的数量
a[i] = avg; // 第i人调整为平均数
a[i + 1] -= t; // 从下一个人处调整
b[i + 1] = t; // 记录传递量
ans += abs(t); // 累加操作次数
}
// 尝试正偏移
for (int i = 1;; i++)
{
int res = calc(i);
if (res > ans) // 如果操作次数增加,停止
{
break;
}
else
{
ans = res; // 更新最少操作次数
}
}
// 尝试负偏移
for (int i = 1;; i++)
{
int res = calc(-i);
if (res > ans)
{
break;
}
else
{
ans = res;
}
}
cout << ans << endl; // 输出最少操作次数
return 0;
}
【运行结果】
5
17 9 14 16 4
11
浙公网安备 33010602011771号