AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC027-D ロボット
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("M+MM-M");
//2
}
else if (InputPattern == "Input2") {
WillReturn.Add("MMM+M");
//1
}
else if (InputPattern == "Input3") {
WillReturn.Add("MMM+--MMM");
//3
}
else if (InputPattern == "Input4") {
WillReturn.Add("+");
//0
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
struct RestInfoDef
{
internal int RestMinusCnt;
internal int RestPlusCnt;
}
static void Main()
{
List<string> InputList = GetInputList();
string S = InputList[0];
// 以降の件数[現在座標]なDict
var RestInfoDict = new Dictionary<int, RestInfoDef>();
int MinusCnt = 0;
int PlusCnt = 0;
int MoveCnt = 0;
for (int I = S.Length - 1; 0 <= I; I--) {
if (S[I] == '-') MinusCnt++;
if (S[I] == '+') PlusCnt++;
if (S[I] == 'M') {
MoveCnt++;
RestInfoDef WillAdd;
WillAdd.RestMinusCnt = MinusCnt;
WillAdd.RestPlusCnt = PlusCnt;
RestInfoDict[I] = WillAdd;
}
}
// +に移動した時の御得度の降順でソート
var MovePlusIndSet = new HashSet<int>();
var Query = RestInfoDict.OrderByDescending(pX => pX.Value.RestPlusCnt - pX.Value.RestMinusCnt);
foreach (var RestInfoDef in Query.Take(MoveCnt / 2)) {
MovePlusIndSet.Add(RestInfoDef.Key);
}
int CurrPos = 0;
int Answer = 0;
for (int I = 0; I <= S.Length - 1; I++) {
if (S[I] == 'M') {
if (MovePlusIndSet.Contains(I)) {
CurrPos++;
}
else {
CurrPos--;
}
}
if (S[I] == '+') {
Answer += CurrPos;
}
if (S[I] == '-') {
Answer -= CurrPos;
}
}
Console.WriteLine(Answer);
}
}
解説
最大スコア[現在位置]でDPすると
O(状態数の2乗)でTLEになるので
アドホックに解きます。
考察すると、
最後に原点に戻らなければならないので、
例えば、Mの個数が10個だと
1増やす移動が5回
1減らす移動が5回
になります。
1増やす移動の得と、
1減らす移動の得は、
ゼロサムゲームなので
1増やす移動での最終スコアの増加の降順で
5箇所が1増やす移動の箇所。
これ以外の5箇所が
1減らす移動の箇所になります。