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で全訪問できるかを判定してます。