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; }