競技プログラミングの鉄則
次の問題へ
前の問題へ
A21 Block Game
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("4");
WillReturn.Add("4 20");
WillReturn.Add("3 30");
WillReturn.Add("2 40");
WillReturn.Add("1 10");
//60
}
else if (InputPattern == "Input2") {
WillReturn.Add("8");
WillReturn.Add("8 100");
WillReturn.Add("7 100");
WillReturn.Add("6 100");
WillReturn.Add("5 100");
WillReturn.Add("4 100");
WillReturn.Add("3 100");
WillReturn.Add("2 100");
WillReturn.Add("1 100");
//400
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
struct PAInfoDef
{
internal int P;
internal int A;
}
static List<PAInfoDef> mPAInfoList = new List<PAInfoDef>();
static void Main()
{
List<string> InputList = GetInputList();
int N = int.Parse(InputList[0]);
int UB = N - 1;
int[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
PAInfoDef WillAdd;
WillAdd.P = wkArr[0] - 1;
WillAdd.A = wkArr[1];
mPAInfoList.Add(WillAdd);
}
// 最大スコア[状態]なDP表
var PrevDP = new Dictionary<int, int>();
JyoutaiDef FirstJyoutai;
FirstJyoutai.LeftRemoveCnt = FirstJyoutai.RightRemoveCnt = 0;
PrevDP[GetHash(FirstJyoutai)] = 0;
for (int I = 1; I <= N; I++) {
var CurrDP = new Dictionary<int, int>();
foreach (var EachPair in PrevDP) {
JyoutaiDef CurrJyoutai = GetJyoutai(EachPair.Key);
JyoutaiDef NextJyoutai;
// 現在の区間を求める
int RangeSta = 0 + CurrJyoutai.LeftRemoveCnt;
int RangeEnd = UB - CurrJyoutai.RightRemoveCnt;
// 先頭を削除の場合
NextJyoutai.LeftRemoveCnt = CurrJyoutai.LeftRemoveCnt + 1;
NextJyoutai.RightRemoveCnt = CurrJyoutai.RightRemoveCnt;
int PVal1 = mPAInfoList[RangeSta].P;
int NewVal1 = EachPair.Value;
if (RangeSta + 1 <= PVal1 && PVal1 <= RangeEnd) {
NewVal1 += mPAInfoList[RangeSta].A;
}
int Hash1 = GetHash(NextJyoutai);
bool WillUpdate1 = true;
if (CurrDP.ContainsKey(Hash1)) {
if (CurrDP[Hash1] >= NewVal1) {
WillUpdate1 = false;
}
}
if (WillUpdate1) {
CurrDP[Hash1] = NewVal1;
}
// 末尾を削除の場合
NextJyoutai.LeftRemoveCnt = CurrJyoutai.LeftRemoveCnt;
NextJyoutai.RightRemoveCnt = CurrJyoutai.RightRemoveCnt + 1;
int PVal2 = mPAInfoList[RangeEnd].P;
int NewVal2 = EachPair.Value;
if (RangeSta <= PVal2 && PVal2 <= RangeEnd - 1) {
NewVal2 += mPAInfoList[RangeEnd].A;
}
int Hash2 = GetHash(NextJyoutai);
bool WillUpdate2 = true;
if (CurrDP.ContainsKey(Hash2)) {
if (CurrDP[Hash2] >= NewVal2) {
WillUpdate2 = false;
}
}
if (WillUpdate2) {
CurrDP[Hash2] = NewVal2;
}
}
PrevDP = CurrDP;
}
Console.WriteLine(PrevDP.Values.Max());
}
struct JyoutaiDef
{
internal int LeftRemoveCnt;
internal int RightRemoveCnt;
}
// ハッシュ値を求める
static int GetHash(JyoutaiDef pJyoutai)
{
return pJyoutai.LeftRemoveCnt * 10000 + pJyoutai.RightRemoveCnt;
}
// ハッシュ値から状態を求める
static JyoutaiDef GetJyoutai(int pHash)
{
JyoutaiDef WillReturn;
WillReturn.LeftRemoveCnt = pHash / 10000;
WillReturn.RightRemoveCnt = pHash % 10000;
return WillReturn;
}
}
解説
区間DPで解いてます。