AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC257-D Jumping Takahashi 2
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("-10 0 1");
WillReturn.Add("0 0 5");
WillReturn.Add("10 0 1");
WillReturn.Add("11 0 1");
//2
}
else if (InputPattern == "Input2") {
WillReturn.Add("7");
WillReturn.Add("20 31 1");
WillReturn.Add("13 4 3");
WillReturn.Add("-10 -15 2");
WillReturn.Add("34 26 5");
WillReturn.Add("-2 39 4");
WillReturn.Add("0 -50 1");
WillReturn.Add("5 -20 2");
//18
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long mN;
struct PosInfo
{
internal long X;
internal long Y;
internal long Power;
}
static List<PosInfo> mPosList = new List<PosInfo>();
static void Main()
{
List<string> InputList = GetInputList();
mN = int.Parse(InputList[0]);
long[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
PosInfo WillAdd;
WillAdd.X = wkArr[0];
WillAdd.Y = wkArr[1];
WillAdd.Power = wkArr[2];
mPosList.Add(WillAdd);
}
long L = 0;
long R = mPosList.Max(pX => pX.X) - mPosList.Min(pX => pX.X)
+ mPosList.Max(pX => pX.Y) - mPosList.Min(pX => pX.Y);
while (L + 1 < R) {
long Mid = (L + R) / 2;
bool IsOK = false;
for (long I = 0; I <= mPosList.Count - 1; I++) {
if (ExecDFS(I, Mid)) {
IsOK = true;
break;
}
}
if (IsOK) {
R = Mid;
}
else {
L = Mid;
}
}
Console.WriteLine(R);
}
struct JyoutaiDef
{
internal long CurrInd;
}
// 始点とSを引数として、DFSで全てのノードに移動可能かを返す
static bool ExecDFS(long pStaNode, long pSVal)
{
var Stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.CurrInd = pStaNode;
Stk.Push(WillPush);
var VisitedSet = new HashSet<long>();
VisitedSet.Add(pStaNode);
while (Stk.Count > 0) {
JyoutaiDef Popped = Stk.Pop();
long CurrX = mPosList[(int)Popped.CurrInd].X;
long CurrY = mPosList[(int)Popped.CurrInd].Y;
for (int I = 0; I <= mPosList.Count - 1; I++) {
if (VisitedSet.Contains(I)) continue;
if (mPosList[(int)Popped.CurrInd].Power * pSVal >=
Math.Abs(CurrX - mPosList[I].X) +
Math.Abs(CurrY - mPosList[I].Y)) {
VisitedSet.Add(I);
WillPush.CurrInd = I;
Stk.Push(WillPush);
}
}
}
return VisitedSet.Count == mN;
}
}
解説
訓練を行う回数を二分探索しつつ
どれかの始点から、DFSで全訪問できるかを判定してます。