P3076 [USACO13FEB] Taxi G 题解
假如你是一个现实生活中的出租车司机,首先容易想到 起码你得把路程开一遍。
那么除开送乘客的时间,那么剩下的就是要最小化接单时间,也就是从上一个终点到下一个起点的时间。
也许你会想到送完一个乘客去找一个最近的起点。然而连样例都过不去。
分析样例,我们从
显然,为了不空载,我们只会在有牛的地方把乘客扔下去。这一瞬间,这个地点存在两头牛。
这两头牛有区别吗?
没有,众生平等。
这时候这两头牛的命运交汇了,你的起点就是我的起点,于是我们在必要的
综上所述,我们要把数组
这里,结论是将
这里的顺序已经和题目中给定的无关了。
无论是小学奥数的小球碰撞,初中化学的复分解反应,还是这道题。
我管你在题目条件里是多么比目鸳鸯双去双来天长地久海枯石烂,都给我拆了!
我只关心我的油费!
至于为什么这个数值最小,可以通过邻项交换证明。 假定
那么必然有
(这回是真的易证了)
另外需要注意的是,由于你从最左端出发,相当于是刚刚拉着你自己到了
同理,最右端是你将要载着自己开始一段新的历程的地方,
#include<algorithm>
#include<cassert>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
#define miu 100007
using namespace std;
inline int abs(register int & x) {
return x > 0 ? x : -x;
}
int n, m;
int s[miu], t[miu];
long long ans = 0;
signed main() {
scanf("%d %d", &n, &m);
t[0] = 0; //看作是刚拉完客等在栅栏左端
s[0] = m; //最后的乘客是你自己,你将驶出栅栏,迈向天涯
for(int i = 1; i <= n; ++i) {
scanf("%d %d", s + i, t + i);
ans += abs(s[i] - t[i]);
}
sort(s, s + n + 1); sort(t, t + n + 1);
for(int i = 0; i <= n; ++i) {
ans += abs(s[i] - t[i]);
}
printf("%lld\n", ans);
}