DPコンテスト
次のDPコンテストの問題へ
前のDPコンテストの問題へ
Educational DP Contest X Tower
C#のソース
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("3");
WillReturn.Add("2 2 20");
WillReturn.Add("2 1 30");
WillReturn.Add("3 1 40");
//50
}
else if (InputPattern == "Input2") {
WillReturn.Add("4");
WillReturn.Add("1 2 10");
WillReturn.Add("3 1 10");
WillReturn.Add("2 4 10");
WillReturn.Add("1 6 10");
//40
}
else if (InputPattern == "Input3") {
WillReturn.Add("5");
WillReturn.Add("1 10000 1000000000");
WillReturn.Add("1 10000 1000000000");
WillReturn.Add("1 10000 1000000000");
WillReturn.Add("1 10000 1000000000");
WillReturn.Add("1 10000 1000000000");
//5000000000
}
else if (InputPattern == "Input4") {
WillReturn.Add("8");
WillReturn.Add("9 5 7");
WillReturn.Add("6 2 7");
WillReturn.Add("5 7 3");
WillReturn.Add("7 8 8");
WillReturn.Add("1 9 6");
WillReturn.Add("3 3 3");
WillReturn.Add("4 1 7");
WillReturn.Add("4 5 5");
//22
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
struct WSVInfoDef
{
internal long W;
internal long S;
internal long V;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();
var WSVInfoList = new List<WSVInfoDef>();
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
WSVInfoDef WillAdd;
WillAdd.W = wkArr[0];
WillAdd.S = wkArr[1];
WillAdd.V = wkArr[2];
WSVInfoList.Add(WillAdd);
}
// W+Sの昇順でソートする
WSVInfoList = WSVInfoList.OrderBy(pX => pX.W + pX.S).ToList();
// 美しさ合計[重さ合計]なDP表
var PrevDP = new Dictionary<long, long>();
PrevDP[0] = 0;
foreach (WSVInfoDef EachWSVInfo in WSVInfoList) {
var CurrDP = new Dictionary<long, long>(PrevDP);
foreach (var EachPair in PrevDP) {
if (EachPair.Key > EachWSVInfo.S) continue;
long NewKey = EachPair.Key + EachWSVInfo.W;
long NewVal = EachPair.Value + EachWSVInfo.V;
if (CurrDP.ContainsKey(NewKey)) {
if (CurrDP[NewKey] >= NewVal) {
continue;
}
}
CurrDP[NewKey] = NewVal;
}
PrevDP = CurrDP;
}
Console.WriteLine(PrevDP.Values.Max());
}
}
解説
最初は、重さ0のものが上にあると考えて
上から順に塔を作ることを考え、
美しさ合計[重さ合計]なDP表
を更新します。
すでにある重さをX
下に置く候補その1のSとWをS1,W1
下に置く候補その2のSとWをS2,W2
とします。
場合1 候補その1,候補その2の順でのみ置ける場合は、
X + W1 <= S2
X + W2 > S1
Xを消去すると、下記が導出できます。
S1 - W2 <= S2 - W1
同値変形して
W1 + S1 <= W2 + S2
場合2 両方とも順番関係なく置ける場合は、
不等式を意識しなくて良いです。
なので、ナップサック問題ですが
W1 + S1 の昇順に設置するのが最適と分かります。