题解 AT4293 [ABC117C] Streamline
这道题是一道贪心,适合初学者用来练习。做完这道题,还可以做与它思路一样的P1209 [USACO1.3]修理牛棚 Barn Repair。
我们可以来看看样例来找思路。拿样例 \(1\) 举例子:
首先将 \(2\) 个棋子分别放在坐标 \(1\) 和 \(10\) ,然后进行 \(5\) 步移动:
坐标 \(1\) 的棋子移动到坐标 \(2\);
坐标 \(10\) 的棋子移动到坐标 \(11\);
坐标 \(11\) 的棋子移动到坐标 \(12\);
坐标 \(12\) 的棋子移动到坐标 \(13\);
坐标 \(13\) 的棋子移动到坐标 \(14\)。
仍拿样例 \(1\) 举例。共用 \(5\) 次操作,怎么减才能使两枚旗子移动的总距离最少呢?显然应该减掉 \(2\) 到 \(10\) 这一段。也就是说,第一枚旗子在坐标 \(1\) - \(2\)范围内移动,第二枚棋子在坐标 \(10\) - \(14\) 范围内移动。其实要求的次数就是长度。
上代码:
#include <iostream>
#include <algorithm>
using namespace std;
int a[100010], d[100010];
bool cmp(int x, int y)
{
return x > y;
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
cin >> a[i];// 首先把m个坐标点输入
}
sort(a + 1, a + m + 1);// 进行由小到大的排序
for (int i = 1; i <= m - 1; i++)
{
d[i] = a[i + 1] - a[i];// 算出任意两点的距离
}
sort(d + 1, d + m, cmp);// 再把距离进行由大到小的排序,注意不要写d + m + 1
// 贪心
int sum = a[m] - a[1];
for (int i = 1; i <= n - 1; i++)
{
sum -= d[i];
}
cout << sum << endl;// 输出答案
return 0;// 结束
}

浙公网安备 33010602011771号