题意:有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 }