AtCoderのABC    次のABCの問題へ    前のABCの問題へ

ABC323-F Push and Carry


問題へのリンク


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("1 2 3 3 0 5");
            //9
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("0 0 1 0 -1 0");
            //6
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("-100000000000000000 -100000000000000000 100000000000000000 100000000000000000 -100000000000000000 -100000000000000000");
            //800000000000000003
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static long[] GetSplitArr(string pStr)
    {
        return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray();
    }

    static long mTakaX;
    static long mTakaY;
    static long mNimotuX;
    static long mNimotuY;
    static long mGoalX;
    static long mGoalY;

    static void Main()
    {
        List<string> InputList = GetInputList();
        long[] wkArr = GetSplitArr(InputList[0]);
        mTakaX = wkArr[0];
        mTakaY = wkArr[1];
        mNimotuX = wkArr[2];
        mNimotuY = wkArr[3];
        mGoalX = wkArr[4];
        mGoalY = wkArr[5];

        // 既にゴールにある場合
        if (mNimotuX == mGoalX && mNimotuY == mGoalY) {
            Console.WriteLine(0);
            return;
        }

        // 処理01 ゴールが(0,0)になるように平行移動
        mTakaX -= mGoalX;
        mTakaY -= mGoalY;
        mNimotuX -= mGoalX;
        mNimotuY -= mGoalY;
        mGoalX = mGoalY = 0;

        // 処理02 荷物が第1象限になるように、X軸で対称移動
        if (mNimotuY < 0) {
            mTakaY *= -1;
            mNimotuY *= -1;
        }

        // 処理03 荷物が第1象限になるように、Y軸で対称移動
        if (mNimotuX < 0) {
            mTakaX *= -1;
            mNimotuX *= -1;
        }

        // 高橋君の目的マスのListを求める
        var DistPosList = new List<PointDef>();
        if (mNimotuX == 0 && mNimotuY > 0) {
            long MoveCost = DeriveMoveCost(mNimotuX, mNimotuY + 1);
            Console.WriteLine(MoveCost + mNimotuY);
            return;
        }
        if (mNimotuX > 0 && mNimotuY == 0) {
            long MoveCost = DeriveMoveCost(mNimotuX + 1, mNimotuY);
            Console.WriteLine(MoveCost + mNimotuX);
            return;
        }

        var AnswerList = new List<long>();
        long MoveCost1 = DeriveMoveCost(mNimotuX + 1, mNimotuY);
        MoveCost1 += mNimotuX;
        MoveCost1 += 2;
        MoveCost1 += mNimotuY;
        AnswerList.Add(MoveCost1);

        long MoveCost2 = DeriveMoveCost(mNimotuX, mNimotuY + 1);
        MoveCost2 += mNimotuX;
        MoveCost2 += 2;
        MoveCost2 += mNimotuY;
        AnswerList.Add(MoveCost2);

        Console.WriteLine(AnswerList.Min());
    }

    struct PointDef
    {
        internal long X;
        internal long Y;
    }

    // 高橋君と目標座標までの移動コストを返す
    static long DeriveMoveCost(long pDistX, long pDistY)
    {
        // マンハッタン距離が最小コスト
        long MoveCost = 0;
        MoveCost += Math.Abs(mTakaX - pDistX);
        MoveCost += Math.Abs(mTakaY - pDistY);

        // 迂回コストが2かかるかを判定
        bool RequireAddCost = false;

        // Y座標が全て等しい場合
        if (mTakaY == mNimotuY && mTakaY == pDistY) {
            if (mTakaX < mNimotuX) {
                RequireAddCost = true;
            }
        }

        // X座標が全て等しい場合
        if (mTakaX == mNimotuX && mTakaX == pDistX) {
            if (mTakaY < mNimotuY) {
                RequireAddCost = true;
            }
        }

        if (RequireAddCost) {
            MoveCost += 2;
        }

        return MoveCost;
    }
}


解説