私は、ナップザック/サブセット和問題の特殊なケースに対処しなければならない問題に取り組んでいました。問題は次のとおりです。
次のようなランダムなサイズが減少する一連のバンドル サイズがあります{47, 35, 22, ...}
。#widgets = 33 のようなウィジェットの数量の値があります。バンドルのウィジェットの数を構成できるバンドルの最小数を見つけます。数量に等しいセットを返す方法がない場合は、null を返します。
- 例 1:
- バンドル サイズ: 46、25、12、4、3
- 数量: 30
- 戻り値: {46:0, 25:0, 12:2, 4:0, 3:2} (バンドルサイズ:バンドルの数)
- 例 2:
- バンドル サイズ: 46、25、12、4、3
- 数量: 17
- 戻り値: {46:0、25:0、12:0、4:2、3:3}
- 例 3:
- バンドル サイズ: 46、25、12、4、3
- 数量: 47
- 戻り値: {46:0、25:1、12:1、4:1、3:2}
- 例 4:
- バンドル サイズ: 46、25、12、4、3
- 数量: 5
- 戻り値: null
この問題をどうするか。
C# でプログラムを作成しました。このプログラムは、十分なジョブを閉じますが、for ループでインデックスをリセットして、残りのセットでは機能しないバンドル サイズをダンプします。それがどこまで進むかについて要求された場合、ソースを投稿します。
要求されたコード:
public List<int> BreakDown(List<int> bunSize, int buySize)
{
List<int> tempBunSize = bunSize.ToList();
tempBunSize.RemoveAll(e => e > buySize);
List<int> ammountNeeded = new List<int>();
int result = buySize;
for (int index = 0; index < tempBunSize.Count; index++)
{
int size = tempBunSize[index];
int tempResult = 0;
double calcResult = 0;
int addAmmount = 0;
if (index == tempBunSize.Count - 2)
{
tempResult = result % size;
if ((tempBunSize.Count > 2 || result % tempBunSize[tempBunSize.Count - 1] == 0))
{
if (result % size != 0)
{
ammountNeeded.Add(0);
tempResult = result % tempBunSize[tempBunSize.Count - 1];
if (tempResult != 0)
{
tempResult = result;
int sizeInc = 0;
while (tempResult != 0)
{
tempResult = tempResult - size;
sizeInc++;
if (tempResult < 0)
{
int decreaseOne = ammountNeeded.First();
ammountNeeded[0] = --decreaseOne;
result = result + tempBunSize.First();
if (ammountNeeded[0] <= 0)
{
tempBunSize.RemoveAt(0);
index = 0;
ammountNeeded = new List<int>();
}
ammountNeeded.Remove(0);
--index;
break;
}
if (tempResult % tempBunSize[tempBunSize.Count - 1] == 0)
{
ammountNeeded.Remove(0);
ammountNeeded.Add(sizeInc);
ammountNeeded.Add(tempResult / tempBunSize[tempBunSize.Count - 1]);
break;
}
}
if (tempResult < 0) continue;
break;
}
else
{
calcResult = result / tempBunSize[tempBunSize.Count - 1];
addAmmount = (int)Math.Floor(calcResult);
ammountNeeded.Add(addAmmount);
break;
}
}
else if (result % size == 0)
{
tempResult = result % size;
if (tempResult != 0 && result % tempBunSize[tempBunSize.Count - 1] != 0)
{
int decreaseOne = ammountNeeded.First();
ammountNeeded.Insert(0, --decreaseOne);
result = result + tempBunSize.First();
continue;
}
else
{
calcResult = result / size;
addAmmount = (int)Math.Floor(calcResult);
ammountNeeded.Add(addAmmount);
if (result % size == 0)
{
ammountNeeded.Add(0);
break;
}
calcResult = result / tempBunSize[tempBunSize.Count - 1];
addAmmount = (int)Math.Floor(calcResult);
ammountNeeded.Add(addAmmount);
break;
}
}
}
else if (tempResult % tempBunSize[tempBunSize.Count - 1] != 0)
{
tempResult = result;
int sizeInc = 0;
while (tempResult != 0)
{
tempResult = tempResult - size;
sizeInc++;
if (tempResult % tempBunSize[tempBunSize.Count - 1] == 0)
{
ammountNeeded.Add(sizeInc);
ammountNeeded.Add(tempResult / tempBunSize[tempBunSize.Count - 1]);
break;
}
}
break;
}
else if (result == 0)
{
while (ammountNeeded.Count < bunSize.Count)
{
ammountNeeded.Add(0);
}
break;
}
else
{
calcResult = result / size;
ammountNeeded.Add((int)Math.Floor(calcResult));
calcResult = tempResult / tempBunSize[tempBunSize.Count - 1];
ammountNeeded.Add((int)Math.Floor(calcResult));
break;
}
}
ammountNeeded.Add((int)Math.Floor((decimal)result / size));
result = result % size;
if (result == 0) continue;
}
if (ammountNeeded.Count < bunSize.Count)
{
ammountNeeded.Reverse(0, ammountNeeded.Count);
while (ammountNeeded.Count < bunSize.Count)
{
ammountNeeded.Add(0);
}
ammountNeeded.Reverse(0, ammountNeeded.Count);
}
if (ammountNeeded.FindLast(e => e < 0) < 0 || ammountNeeded.Sum() == 0)
return null;
return ammountNeeded;
}
}