AOJ本の読書メモ
AOJ
次のAOJの問題へ
前のAOJの問題へ
AOJ 0611 シルクロード
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 5");
WillReturn.Add("10");
WillReturn.Add("25");
WillReturn.Add("15");
WillReturn.Add("50");
WillReturn.Add("30");
WillReturn.Add("15");
WillReturn.Add("40");
WillReturn.Add("30");
//1125
}
else if (InputPattern == "Input2") {
WillReturn.Add("2 6");
WillReturn.Add("99");
WillReturn.Add("20");
WillReturn.Add("490");
WillReturn.Add("612");
WillReturn.Add("515");
WillReturn.Add("131");
WillReturn.Add("931");
WillReturn.Add("1000");
//31589
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = InputList[0].Split(' ').Select(pX => long.Parse(pX)).ToArray();
long N = wkArr[0];
long M = wkArr[1];
// ゴールノード
long GoalNode = N;
// 待機回数の上限
long WaitLimit = M - N;
var DistanceList = new List<long>();
foreach (string EachStr in InputList.Skip(1).Take((int)N)) {
DistanceList.Add(long.Parse(EachStr));
}
var WeatherList = new List<long>();
foreach (string EachStr in InputList.Skip(1 + (int)N)) {
WeatherList.Add(long.Parse(EachStr));
}
// コスト[現在ノード,休んだ回数]なDP表
var PrevDP = new Dictionary<long, long>();
JyoutaiDef FirstJyoutai;
FirstJyoutai.Pos = 0;
FirstJyoutai.WaitCnt = 0;
PrevDP[GetHash(FirstJyoutai)] = 0;
var AnswerList = new List<long>();
foreach (long EachWeather in WeatherList) {
var CurrDP = new Dictionary<long, long>();
foreach (var EachPair in PrevDP) {
Action<JyoutaiDef, long> UpdateAct = (pNewJyoutai, pNewVal) =>
{
long Hash = GetHash(pNewJyoutai);
if (CurrDP.ContainsKey(Hash)) {
if (CurrDP[Hash] <= pNewVal) {
return;
}
}
CurrDP[Hash] = pNewVal;
};
// 移動する場合
JyoutaiDef CurrJyoutai1 = GetJyoutai(EachPair.Key);
long CurrDistance = DistanceList[(int)CurrJyoutai1.Pos];
CurrJyoutai1.Pos++;
long NewVal = EachPair.Value + CurrDistance * EachWeather;
if (CurrJyoutai1.Pos == GoalNode) {
AnswerList.Add(NewVal);
}
else {
UpdateAct(CurrJyoutai1, NewVal);
}
// 待機する場合
JyoutaiDef CurrJyoutai2 = GetJyoutai(EachPair.Key);
CurrJyoutai2.WaitCnt++;
if (CurrJyoutai2.WaitCnt <= WaitLimit) {
UpdateAct(CurrJyoutai2, EachPair.Value);
}
}
PrevDP = CurrDP;
}
Console.WriteLine(AnswerList.Min());
}
struct JyoutaiDef
{
internal long Pos;
internal long WaitCnt;
}
static long GetHash(JyoutaiDef pJyoutai)
{
return pJyoutai.Pos * 100000000 + pJyoutai.WaitCnt;
}
static JyoutaiDef GetJyoutai(long pHash)
{
JyoutaiDef WillReturn;
WillReturn.Pos = pHash / 100000000;
WillReturn.WaitCnt = pHash % 100000000;
return WillReturn;
}
}
解説
コスト[現在ノード,休んだ回数]でDPしてます。
枝切り用で、休める上限を最初に求めてます。