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 }
View Code

 

 

posted on 2013-06-10 21:09  KimKyeYu  阅读(189)  评论(0编辑  收藏  举报

导航