user-0 提问: 求一个平衡分组算法

回复:
user: user-0
content: 楼上可能没理解我的意思啊，现在是背景类似这样 有12个实力权重值分别为1-12的选手，分成3组，要求各组选手的权重之和要相等或接近，求一个算法。

user: user-1
content: 仅供参考//给出12个随机数,分成三组求和,每组的个数不定,要求求出来的三个数之间相差最小,最完美的情况是三个数相等. #include <stdlib.h> #include <stdio.h> #include <time.h> #include <math.h> #include <limits.h> int i,j,k; int g[12][3]={//可能的分组大小     { 1, 1,10},     { 1, 2, 9},     { 1, 3, 8},     { 1, 4, 7},     { 1, 5, 6},     { 2, 2, 8},     { 2, 3, 7},     { 2, 4, 6},     { 2, 5, 5},     { 3, 3, 6},     { 3, 4, 5},     { 4, 4, 4}, }; int n[12]; int m[12]; int f[12];//当前最小时各数 int g1,g2,g3;//1,2,3组可分配的个数 int n1,n2,n3;//1,2,3组已分配的个数 int f1,f2;//当前最小时1,2组的个数 int s1,s2,s3;//123组的和 int d;//1-2,2-3,3-1组中各数和之间差的绝对值之和 int dmin=INT_MAX;//保存当前d的最小值 void swap(int *pi1,int *pi2) {     int t;     t=*pi1;*pi1=*pi2;*pi2=t; } void test() {     s1=0;     for (i=0;i<g1;i++) s1=s1+n[i];     s2=0;     for (i=g1;i<g1+g2;i++) s2=s2+n[i];     s3=0;     for (i=g1+g2;i<12;i++) s3=s3+n[i];     d=abs(s1-s2)+abs(s2-s3)+abs(s3-s1);     if (d<dmin) {         dmin=d;         f1=g1;         f2=g2;         for (i=0;i<12;i++) f[i]=n[i];         printf("(");         for (i=0;i<g1;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1;i<g1+g2;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1+g2;i<12;i++) printf("%2d,",n[i]);         printf(") %4d\n",dmin);     } else {         printf("(");         for (i=0;i<g1;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1;i<g1+g2;i++) printf("%2d,",n[i]);         printf(")  (");         for (i=g1+g2;i<12;i++) printf("%2d,",n[i]);         printf(") %4d\n",d);     } } void main() {     srand(time(NULL));     for (i=0;i<12;i++) m[i]=rand()%100;     for (i=0;i<12;i++) printf("%2d,",m[i]);     printf("\n");     for (i=1;i<12;i++) {         for (j=0;j<i;j++) {             if (m[i]>m[j]) swap(&m[i],&m[j]);//冒泡排序从大到小         }     }     for (i=0;i<12;i++) printf("%2d,",m[i]);     printf("\n");     for (k=0;k<12;k++) {//在12种分组方法中         //取第i种分组方法         g1=g[k][0];         g2=g[k][1];         g3=g[k][2];         printf("%2d-%2d,%2d,%2d\n",k,g1,g2,g3);         //将从大到小12个数双向轮流分配到三个组中         n1=0;         n2=0;         n3=0;         for (j=0;j<12;j++) {             switch (j%6) {             case 0:         redo:                 if (n1<g1) {                     n[n1]=m[j];                     n1++;                     break;                 }             case 1:                 if (n2<g2) {                     n[g1+n2]=m[j];                     n2++;                     break;                 }             case 2:                 if (n3<g3) {                     n[g1+g2+n3]=m[j];                     n3++;                     break;                 }             case 3:                 if (n3<g3) {                     n[g1+g2+n3]=m[j];                     n3++;                     break;                 }             case 4:                 if (n2<g2) {                     n[g1+n2]=m[j];                     n2++;                     break;                 }             case 5:                 if (n1<g1) {                     n[n1]=m[j];                     n1++;                     break;                 }             default:goto redo;             }         }         test();     }     printf("---------------------------------------------------\n");     g1=f1;     g2=f2;     for (i=0;i<12;i++) n[i]=f[i];     printf("(");     for (i=0;i<g1;i++) printf("%2d,",n[i]);     printf(")  (");     for (i=g1;i<g1+g2;i++) printf("%2d,",n[i]);     printf(")  (");     for (i=g1+g2;i<12;i++) printf("%2d,",n[i]);     printf(") %4d\n",dmin); }