問題へのリンク
using System; using System.Collections.Generic; using System.Linq; class Program { static string InputPattern = "InputX"; static List<string> GetInputList() { var WillReturn = new List<string>(); if (InputPattern == "Input1") { WillReturn.Add("4 8"); WillReturn.Add("4 3 2"); WillReturn.Add("2 1 1"); WillReturn.Add("1 2 4"); WillReturn.Add("3 2 2"); //12 } else if (InputPattern == "Input2") { WillReturn.Add("2 100"); WillReturn.Add("1 1 100"); WillReturn.Add("2 1 50"); //150 } else { string wkStr; while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr); } return WillReturn; } struct ItemInfoDef { internal long Value; internal long Weight; } static List<ItemInfoDef> mItemInfoList = new List<ItemInfoDef>(); static void Main() { List<string> InputList = GetInputList(); long[] wkArr = { }; Action<string> SplitAct = pStr => wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray(); SplitAct(InputList[0]); long WeightLimit = wkArr[1]; foreach (string EachStr in InputList.Skip(1)) { SplitAct(EachStr); long Value = wkArr[0]; long Weight = wkArr[1]; long Cnt = wkArr[2]; var Beki2List = new List<long>(); while (Cnt > 0) { var ResultBeki2List = DeriveBeki2List(ref Cnt); Beki2List.AddRange(ResultBeki2List); } foreach (long EachCnt in Beki2List) { ItemInfoDef WillAdd; WillAdd.Value = Value * EachCnt; WillAdd.Weight = Weight * EachCnt; mItemInfoList.Add(WillAdd); } } // 最大価値[重さ合計]なインラインDP表 long UB = WeightLimit; long?[] DPArr = new long?[UB + 1]; DPArr[0] = 0; foreach (ItemInfoDef EachItem in mItemInfoList) { for (long I = UB; 0 <= I; I--) { if (DPArr[I].HasValue == false) continue; long NewI = I + EachItem.Weight; if (NewI > UB) continue; long NewVal = DPArr[I].Value + EachItem.Value; if (DPArr[NewI].HasValue) { if (DPArr[NewI].Value >= NewVal) { continue; } } DPArr[NewI] = NewVal; } } Console.WriteLine(DPArr.Max()); } static List<long> DeriveBeki2List(ref long pVal) { var Beki2List = new List<long>(); long Beki2 = 1; while (true) { if (pVal < Beki2) break; Beki2List.Add(Beki2); pVal -= Beki2; Beki2 *= 2; } return Beki2List; } }
下記のように、ダブリングの考え方を使用してます。 品物が100個使える場合 1+2+4+8+16+32 = 63 100 - 63 = 37 1+2+4+8+16 = 31 37 - 31 = 6 1+2 = 3 6 - 3 = 3 1+2 = 3 で、1,2,4,8,16,32,1,2,4,8,16,1,2,1,2 ずつ使用できるとして、 DPの遷移回数を減らしてます。