興味深い。このCプログラムはこれまで予想されていた結果を出すようです。それはデータを並べ替えることから始まり、次にnのコンテナの場合は、すぐにnのそれぞれの番号が格納されます。 (実際にそのステップを省略することができます)。次に、最大の残りの数値から最小の値まで、その数値を加算すると、との差が最小となるコンテナが見つかる。これは高い値から低い値へと変化するため、各数値は最適なコンテナに格納されます。他の数値はすべて低くなりますので、それらの差はさらに大きくなります。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
int sort_numeric (const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
int main (int argc, char **argv)
{
int list[] = { 10, 30, 503, 23, 1, 85, 355 };
int i,j, nnumber, ncontainer, total, avgPerContainer, nextError, smallestError, containerForSmallest;
int *containers, *errors;
ncontainer = 3;
nnumber = sizeof(list)/sizeof(list[0]);
qsort (list, nnumber, sizeof(list[0]), sort_numeric);
containers = (int *)malloc(ncontainer * sizeof(int));
for (i=0; i<ncontainer; i++)
containers[i] = 0;
errors = (int *)malloc(ncontainer * sizeof(int));
for (i=0; i<ncontainer; i++)
errors[i] = 0;
printf ("input:");
for (i=0; i<nnumber; i++)
{
printf (" %d", list[i]);
}
printf ("\n");
// how much is to be in each container?
total = 0;
for (i=0; i<nnumber; i++)
total += list[i];
// this will result in a fraction:
// avgPerContainer = total/ncontainer;
// so instead we'll use 'total' and *keeping in mind*
// that the number needs to be divided by ncontainer
avgPerContainer = total;
printf ("per container: ~%d\n", (2*avgPerContainer+ncontainer)/(2*ncontainer));
// start by putting highest values into each container
for (i=0; i<ncontainer; i++)
containers[i] += list[nnumber-ncontainer+i];
// .. remove from list ..
nnumber -= ncontainer;
// print current totals
for (i=0; i<ncontainer; i++)
{
errors[i] = containers[i]*ncontainer - avgPerContainer;
printf ("#%d: %d, error = %d/%d ~ %+d\n", i, containers[i], errors[i], ncontainer, (2*errors[i]+ncontainer)/(2*ncontainer));
}
printf ("remaining:");
for (i=0; i<nnumber; i++)
{
printf (" %d", list[i]);
}
printf ("\n");
// add the remainders
for (i=nnumber-1; i>=0; i--)
{
smallestError = INT_MAX;
containerForSmallest = 0;
for (j=0; j<ncontainer; j++)
{
nextError = (containers[j] + list[i]) - avgPerContainer;
if (nextError < smallestError)
{
containerForSmallest = j;
smallestError = nextError;
printf ("error for %d, %d + %d, is %+d\n", j, containers[j], list[i], smallestError);
}
}
printf ("we put %d into #%d\n", list[i], containerForSmallest);
containers[containerForSmallest] += list[i];
}
for (i=0; i<ncontainer; i++)
{
printf ("#%d: %d, error = %d/%d ~ %+d\n", i, containers[i], containers[i]*ncontainer - avgPerContainer, ncontainer, (2*(containers[i]*ncontainer - avgPerContainer)+ncontainer)/(2*ncontainer));
}
return 0;
}
非常に難しい問題です。私は、最適な解決策を得るための簡単な方法があるとは思っていません。あなたは「可能な限り」であなたが意味するものを指定する必要があります。 3つ以上の容器では、それが何を意味するのかは不明です。 – john
残念ながら、あなたの現在のアプローチは、「可能な限り」配分をしないという意味では間違っています。 '{1000,501,500,1} 'という集合を2つのコンテナに分類して考えてみましょう。 – us2012
良いハッシュ関数の設計のように思えます。 – Arpit