
Farmer John went to cut some wood and left N (2 ≤ N ≤ 100,000) cows eating the grass, as usual. When he returned, he found to his horror that the cluster of cows was in his garden eating his beautiful flowers. Wanting to minimize the subsequent damage, FJ decided to take immediate action and transport each cow back to its own barn.
Each cow i is at a location that is Ti minutes (1 ≤ Ti ≤ 2,000,000) away from its own barn. Furthermore, while waiting for transport,she destroys Di (1 ≤ Di ≤ 100)...
题目
1.题目大意
- 农场 \(n\) 头牛,都在吃花,农民 \(John\) 心碎了,要把牛搬回牛棚,问如何损失花最小(求最小值)
- 搬运第 \(i\) 头牛到牛棚花费时间 \(t_i\)(往返则是 \(2t_i\)),每头牛每个单位时间吃花量为 \(d_i\)
- 初始在牛的位置,从一头牛走到另一头牛的时间不计
2.题目分析
- 有两个参数 \(t\) 和 \(d\),我们只需要根据参数排好序再计算结果即可
- 排序的依据为(先运 \(a\)):\(t_a*d_b<t_b*d_a\)
- 主要有两种推导思路
- \(t_a*(d_b+Rd)+t_b*Rd<t_b*(d_a+Rd)+t_a*Rd\)
从剩下的牛中选择两头 \(a\) 和 \(b\) 进行排序,\(Rd\) 为剩下的所有牛(除了 \(a\) 和 \(b\))的 \(d\) 之和
上式的含义为先运牛 \(a\) 比先运牛 \(b\) 的剩余代价小(因为前面的代价相同)
式中每一项都需要乘二(往返),所以直接约掉了,最后化简后可以得到排序的依据
- \(Dt*d_a+(Dt+2*t_a)*d_b<Dt*d_b+(Dt+2*t_b)*d_a\)
从剩下的牛中选择两头 \(a\) 和 \(b\) 进行排序,\(Dt\) 为前面搬运完的所有牛的 \(t\) 之和
上式的含义为在先运牛 \(a\) 比先运牛 \(b\) 的代价小(包含从开始的两头牛的代价)
也可以理解为在已经运完的牛的总代价基础上加上运牛 \(a\) 比加上运牛 \(b\) 的代价小(已经运完的代价相同,可以直接约掉)
3.题目代码
#include <bits/stdc++.h>
using namespace std;
typedef struct cow{
int t;
int d;
}cow;
bool cmp(cow a, cow b)
{
return a.t * b.d < b.t * a.d;
}
int main() {
int n;
cin >> n;
cow cc[n];
long long sum = 0;
long long ans = 0;
for(int i=0;i<n;i++)
{
cin >> cc[i].t >> cc[i].d;
sum += cc[i].d;
}
sort(cc, cc+n, cmp);
for(int i=0;i<n-1;i++)
{
sum -= cc[i].d;
ans += sum * cc[i].t * 2;
}
cout << ans << endl;
}