noip模拟赛 护花

题目描述

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

输入输出格式

输入格式:

 

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
6
3 1
2 5
2 3
3 2
4 1
1 6
输出样例#1:
86
【样例解释】
 约翰用6,2,3,4,1,5的顺序来运送他的奶牛
分析:要安排顺序,很显然是一道贪心题,那么要怎么安排顺序呢?
还是依靠贪心的一般套路,选2头牛a,b,假设(a,b)是最佳的顺序,如果交换a,b,那么答案一定会比不交换差,也就是说要ta*db*2 < tb*da*2,推广到一般情况也是一样的,依照这个排序然后模拟一下就好了。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 100010;

int n,sum;
long long ans;

struct node
{
    int t, d;
}e[maxn];

bool cmp(node a, node b)
{
    return a.t * b.d < a.d * b.t;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d%d", &e[i].t, &e[i].d);
        sum += e[i].d;
    }
    sort(e + 1, e + 1 + n, cmp);
    for (int i = 1; i <= n; i++)
    {
        sum -= e[i].d;
        ans += sum * e[i].t * 2;
    }
    printf("%lld\n", ans);

    return 0;
}

 

 
posted @ 2017-09-19 21:04  zbtrs  阅读(174)  评论(0编辑  收藏  举报