POJ 3262题目大意如下:
还是关于Fermer John 和他的奶牛的故事,FJ有一个花园,里面种了很多花。每天FJ会带牛在外面吃草,牛群回来之后,在FJ不注意的时候会吃掉花园里的花,所以FJ需要把牛群运到它们的牛棚里去。每次只能运送一头牛,给出了运送每头牛所花的时间和每头牛能够每单位时间吃掉的花的数量,现在要求给出一个最优方案,使得FJ损失的花数量最少。
一开始想的太简单,看到题目给出的数据实例,直接写了一个先按照运送时间从小到大排序,再考虑同时间内的吃掉花的数量从大到小排序,结果wrong了一发。后来想到这样排序没有任何意义因为我不能保证虽然说每次运送的那头牛花的时间最少,但是对于接下来的牛我没有考虑它们吃花的速度,所以得出来的方案当然是错的。
所以现在这样考虑,对于任意两头牛A和B,我知道它们的其他数据(时间为time,吃花速度为speed),接下来考虑两种情况(考虑来回):
1)如果A在B前面,那么针对这两头牛而言,消耗的花的数量为:Cost(A, B) = 2*A.time*B.speed;
2)如果B在A前面,那么针对这两头牛而言,消耗的花的数量为:Cost(B, A) = 2*B.time*A.speed;
现在比较Cost(A, B) 和Cost(B, A),根据这两个值的大小,我们就可以确定A和B那头牛在前了。而这是从任意两头牛的角度来看的,所以对于整个数据群,按照这样的运送方案,就是最优,代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 100000;
pair<int, int> cost[maxn + 5];
struct Cow {
int time, speed;
unsigned long long int add;
}cow[maxn + 5];
int camp(const void* lhs, const void* rhs) {
Cow* p1 = (Cow*)lhs;
Cow* p2 = (Cow*)rhs;
return p1->time*p2->speed - p1->speed*p2->time;
}
void solve(int N) {
unsigned long long int sum = 0;
qsort(cow, N, sizeof(Cow), camp);
cow[1].add = cow[0].time*2;
sum += cow[1].add*cow[1].speed;
int i = 2;
while (i < N) {
cow[i].add = cow[i - 1].add + cow[i - 1].time*2;
sum += cow[i].add*cow[i].speed;
i++;
}
printf("%llu\n", sum);
}
int main(int argc, const char * argv[]) {
// insert code here...
int N;
scanf("%d", &N);
for (int i = 0; i < N; i++) {
scanf("%d %d", &cow[i].time, &cow[i].speed);
}
solve(N);
return 0;
}