poj 1862 Stripies
http://poj.org/problem?id=1862
题意描述:
有n个生物,体重为w1, w2, ... , wn;任意两个生物可合成为一个生物;
其体重w'满足:w' = 2sqrt(wi * wj); 如此反复,终将得到一个生物,体重为W。
适当调整合成顺序,使得W最小。
思路:贪心
每次取体重最大的两个生物先合成。
证明:
不妨设w1>w2>...>wn, f(a, b) = 2sqrt(a*b);
那么按照贪心策略: W = f(f(... f(f(w1, w2), w3) ...), wn); (1)
Hint:(1)式正确,是因为f(w1, w2)合成后,一定还是最大!!
化简有: W = C*∏(wi ^ ai), 且∑ai = 1; //其中C为常数, i∈[1, n];
注意到ai为1/2的整数幂,且wi的迭代次数递减,
故ai递增,即 0<a1<a2<..<an<1;
w1已经为最大(w1 >= wi),那么考虑交换w1与wi; (2<i<=n)
有Wi - W1 = M*(wi^a1 * w1^ai - w1^a1 * wi^ai) = M* wi^a1 * w1^a1 * [w1^(ai-a1) - wi^(ai-a1)] >= 0;
也即交换总使得W增大(或不变),所以不该交换,即每次选最大是合理的。
w2同理选次大。
ps:本来想暴搜,苦于不会剪枝~~。
1 #include <iostream> 2 #include <stdio.h> 3 #include <string> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <math.h> 7 #define INF 0x3f3f3f3f 8 using namespace std; 9 10 int n; 11 double num[105]; 12 int cmp(const void *a, const void *b) 13 { 14 return *(double *)a - *(double *)b; 15 } 16 17 int main() 18 { 19 //freopen("testin.txt", "r", stdin); 20 //freopen("testout.txt", "w", stdout); 21 22 while(cin >> n) 23 { 24 for(int i=0; i<n; i++) 25 cin >> num[i]; 26 27 qsort(num, n, sizeof(double), cmp); 28 while(n > 1) 29 { 30 num[n-2] = sqrt(num[n-2]*num[n-1])*2;//这里num[n-2]总是最大的,故不必排序。 31 32 n--; 33 } 34 35 printf("%.3f\n", num[0]); 36 } 37 38 return 0; 39 }