POJ 2576 Tug of War 随机算法(非正规解法)

题意:有n个人要分成两队进行拔河比赛,要求两队人数之差不超过1,且体重之和尽可能接近。

 

思路:先按体重从小到大排序,然后把前一半划为a队,后一半划为b队,算出体重之差作为当前最小值。生成两个随机数x,y,作为进行交换的队员编号,即把a队的x号队员放到b队,把b队的y号队员放到a队,检查交换后体重之差是否更小,若是则交换过来并记录新的最小值,否则不交换。重复操作N次,只要RP足够好即可AC。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <stdlib.h>
 4 #include <time.h>
 5 using namespace std;
 6 
 7 int main(void)
 8 {
 9     srand((unsigned)time(NULL));
10     int N, n, a[110], b[55], c[55], nb, nc, sumb, sumc, close, x, y, sx, sy;
11     while(~scanf("%d", &n))
12     {
13         for(int i=0; i<n; ++i)
14             scanf("%d", a+i);
15         if(n==1)
16         {
17             printf("0 %d
", a[0]);
18             continue;
19         }
20         sort(a, a+n);
21         sumb = sumc = 0;
22         if(n&1)
23         {
24             nb = n/2+1;
25             nc = n - nb;
26             int i = 0;
27             for(; i<nb; ++i)
28                 b[i] = a[i], sumb += a[i];
29             for(; i<n; ++i)
30                 c[i-nb] = a[i], sumc += a[i];
31         }
32         else
33         {
34             nb = nc = n/2;
35             int i = 0;
36             for(; i<nb; ++i)
37                 b[i] = a[i], sumb += a[i];
38             for(; i<n; ++i)
39                 c[i-nb] = a[i], sumc += a[i];
40         }
41         close = abs(sumb-sumc);
42         N = 1000000;
43         while(N--)
44         {
45             x = rand() % nb;
46             y = rand() % nc;
47             sx = sumb - b[x] + c[y];
48             sy = sumc + b[x] - c[y];
49             if(abs(sx-sy) < close)
50             {
51                 sumb = sx;
52                 sumc = sy;
53                 b[x] ^= c[y], c[y] ^= b[x], b[x] ^= c[y];
54                 close = abs(sx-sy);
55             }
56         }
57         if(sumb > sumc)
58             sumb ^= sumc, sumc ^= sumb, sumb ^= sumc;
59         printf("%d %d
", sumb, sumc);
60     }
61 }
原文地址:https://www.cnblogs.com/corvey/p/4779298.html