题目描述:

你是一个牧场主,你放牛吃草后,有出去砍树了。当你回来的时候,你发现你的牛在吃你心爱的小花,为了防止你的小花被吃,你只能把这些可恶的牛赶回他们的窝。。。但是你只有一个人,所以一次只能赶回一只牛,在你赶它们回去的时候,他们还在持续的吃草,而且根据牛个体的不同,赶回他们所需要的时间 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;
}