题目描述:
你是一个牧场主,你放牛吃草后,有出去砍树了。当你回来的时候,你发现你的牛在吃你心爱的小花,为了防止你的小花被吃,你只能把这些可恶的牛赶回他们的窝。。。但是你只有一个人,所以一次只能赶回一只牛,在你赶它们回去的时候,他们还在持续的吃草,而且根据牛个体的不同,赶回他们所需要的时间 t[i]*2 和它们在没有被赶的时候的吃草的速度也不同,所以你要想出一个赶牛的顺序,使得你的小花损失的最少。
题解:
我们可以发现,当我们更换赶回去的两头牛的顺序的时候,当他们本来就是一前一后被赶回去时,他们产生的效果不会影响别的牛,只会对总小花产生影响。
因此我们只要找出“先赶回去的牛”和“后赶回去的牛”满足是最佳策略时的条件,就可以产生一个赶牛回去的最佳顺序排列。
如果我们规定 A 牛在 B 牛前面时满足最佳策略。那么,AB这种顺序时这两个牛吃的草,要小于BA顺序时这两头牛吃的草。现在我们来看 AB顺序时,小花的减少量=A的时间*A的吃草量+(A的时间+B的时间)*B的吃草量, BA顺序时,小花的减少量= B的时间*B的吃草量+(A的时间+B的时间)*A的吃草量,我们使AB<BA对这个式子消项得A的吃草/A的时间<B的吃草/B的时间,因此,我们只需要对每只牛的吃草量/时间进行排序,就可以得到赶牛顺序了!
代码:
#include<iostream> #include<algorithm> using namespace std; const int N = 100010; struct cow { double ans; long long t; long long d; bool operator < (const cow a)const { if (ans != a.ans) return ans < a.ans; else if (t < a.t) return t < a.t; return d < a.d; } }cnt[1000010]; int main() { int n; cin >> n; long long temp = 0; for (int i = 0; i < n; i++) { cin >> cnt[i].t >> cnt[i].d; temp += cnt[i].d; cnt[i].ans = ((double)cnt[i].t) / ((double)cnt[i].d); } sort(cnt, cnt + n); long long res = 0; for (int i = 0; i < n; i++) { temp -= cnt[i].d; res += cnt[i].t * 2 * temp; } cout << res; return 0; }