bzoj1634护花

试题描述:

约翰留下他的N(N<=100000)只奶牛上山采木.他离开的时候,她们像往常一样悠闲地在草场里吃草.可是,当他回来的时候,他看到了一幕惨剧:牛们正躲在他的花园里,啃食着他心爱的美丽花朵!为了使接下来花朵的损失最小,约翰赶紧采取行动,把牛们送回牛棚. 牛们从1到N编号.第i只牛所在的位置距离牛棚Ti(1≤Ti≤2000000)分钟的路程,而在约翰开始送她回牛棚之前,她每分钟会啃食Di(1≤Di≤100)朵鲜花.无论多么努力,约翰一次只能送一只牛回棚.而运送第第i只牛事实上需要2Ti分钟,因为来回都需要时间.    写一个程序来决定约翰运送奶牛的顺序,使最终被吞食的花朵数量最小.

输入:

第1行输入N,之后N行每行输入两个整数Ti和Di

输出:

一个整数,表示最小数量的花朵被吞食

输入示例:

6
3 1
2 5
2 3
3 2
4 1
1 6

输出示例:

86

样例解释:

约翰用6,2,3,4,1,5的顺序来运送他的奶牛 

解题思路:

我开始蒙按D从大到小排,一样的按T从小到大拍,结果只过了3个点(还过了三个点?!)然后打算好好地堆贪心公式。

我们来看i和i+1这两头牛。

Ti     Ti+1

Di    Di+1

如果i在前面,那么这两头牛所耗费的价值是2Ti*Di+1,如果i+1,则价值为2Ti+1*Di只要看这两个值哪个大,就把哪个排前面。

贪心公式出来了

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
long long sum[100010];
long long n;
long long ans = 0;
struct node
{
    long long t, d;
    int index;
}input[100010];
bool cnp(node a,node b)
{
    return a.t*b.d<a.d*b.t;//贪心公式
}
int main()
{
    freopen("flower.in", "r", stdin);
    freopen("flower.out", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> input[i].t >> input[i].d;
        input[i].index = i;
    }
    sort(input + 1, input + n + 1, cnp);
    for (int i = n; i >= 1; i--)
        sum[i] = sum[i + 1] + input[i].d;
    for (int i = 1; i <= n; i++)
    {
        int k = input[i].t * 2;
        ans += k*sum[i + 1];
    }
    cout << ans;
}

 

posted @ 2017-08-16 16:00  Dijkstra·Liu  阅读(310)  评论(0编辑  收藏  举报