题意:给你C个小组(C<=5),S个数值(S<=10, C*2>=S)。要将这S个数值分配给C个小组,每小组最多分配两个数值。求最优的分配方式,使得下面 IMBALANCE 的值最小。
其中AM = 所有数值之和 / C; CMi = 第i小组的数值之和;
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
int C, S;
double imb, am;
int ch[6][3], tmp[6][3]; //ch[i][0]表示第i小组所分配的数值个数; tmp记录临时的分配方式
int sp[11];
void DFS(int id)
{
if(id > S)
{
double s, sum = 0;
for(int i = 1; i <= C; i++)
{
s = 0;
for(int j = 1; j <= tmp[i][0]; j++)
s += tmp[i][j];
sum += fabs(s - am);
if(sum >= imb) return;
}
imb = sum;
memcpy(ch,tmp,sizeof(tmp));
return;
}
for(int i = 1; i <= C; i++)
{
if(tmp[i][0] == 2) continue;
tmp[i][++tmp[i][0]] = sp[id];
DFS(id + 1);
tmp[i][0]--;
}
}
void output(int cs)
{
printf("Set #%d\n",cs);
for(int i = 1; i <= C; i++)
{
printf(" %d:",i-1);
for(int j = 1; j <= ch[i][0]; j++)
printf(" %d",ch[i][j]);
printf("\n");
}
printf("IMBALANCE %.5lf\n\n",imb);
}
int main()
{
int cs = 0;
while(scanf("%d%d",&C,&S) != EOF)
{
am = 0; imb = 999999.9;
memset(ch,0,sizeof(ch));
memset(tmp,0,sizeof(tmp));
for(int i = 1; i <= S; i++)
{
scanf("%d",&sp[i]);
am += sp[i];
}
am /= C;
DFS(1);
output(++cs);
}
return 0;
}