AtCoderの企業コンテスト    次の企業コンテストの問題へ    前の企業コンテストの問題へ

ディスカバリーチャンネル 2020 予選 C Strawberry Cakes


問題へのリンク


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("3 3 5");
            WillReturn.Add("#.#");
            WillReturn.Add(".#.");
            WillReturn.Add("#.#");
            //1 2 2
            //1 3 4
            //5 5 4
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("3 7 7");
            WillReturn.Add("#...#.#");
            WillReturn.Add("..#...#");
            WillReturn.Add(".#..#..");
            //1 1 2 2 3 4 4
            //6 6 2 2 3 5 5
            //6 6 7 7 7 7 7
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("13 21 106");
            WillReturn.Add(".....................");
            WillReturn.Add(".####.####.####.####.");
            WillReturn.Add("..#.#..#.#.#....#....");
            WillReturn.Add("..#.#..#.#.#....#....");
            WillReturn.Add("..#.#..#.#.#....#....");
            WillReturn.Add(".####.####.####.####.");
            WillReturn.Add(".....................");
            WillReturn.Add(".####.####.####.####.");
            WillReturn.Add("....#.#..#....#.#..#.");
            WillReturn.Add(".####.#..#.####.#..#.");
            WillReturn.Add(".#....#..#.#....#..#.");
            WillReturn.Add(".####.####.####.####.");
            WillReturn.Add(".....................");
            //12 12 23 34 45 45 60 71 82 93 93 2 13 24 35 35 17 28 39 50 50
            //12 12 23 34 45 45 60 71 82 93 93 2 13 24 35 35 17 28 39 50 50
            //12 12 56 89 89 89 60 104 82 31 31 46 13 24 35 35 61 61 39 50 50
            //12 12 67 67 100 100 60 9 9 42 42 57 13 24 6 72 72 72 72 72 72
            //12 12 78 5 5 5 20 20 20 53 68 68 90 24 6 83 83 83 83 83 83
            //16 16 27 38 49 49 64 75 86 97 79 79 90 101 6 94 94 105 10 21 21
            //16 16 27 38 49 49 64 75 86 97 79 79 90 101 6 94 94 105 10 21 21
            //32 32 43 54 65 65 80 11 106 95 22 22 33 44 55 55 70 1 96 85 85
            //32 32 43 54 76 76 91 11 106 84 84 4 99 66 66 66 81 1 96 74 74
            //14 14 3 98 87 87 102 11 73 73 73 4 99 88 77 77 92 92 63 63 63
            //25 25 3 98 87 87 7 29 62 62 62 15 99 88 77 77 103 19 30 52 52
            //36 36 47 58 69 69 18 29 40 51 51 26 37 48 59 59 8 19 30 41 41
            //36 36 47 58 69 69 18 29 40 51 51 26 37 48 59 59 8 19 30 41 41
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static char[,] mCharBanArr;
    static int UB_X;
    static int UB_Y;

    static int[,] mIntBanArr;

    static void Main()
    {
        List<string> InputList = GetInputList();
        mCharBanArr = CreateBanArr(InputList.Skip(1));
        UB_X = mCharBanArr.GetUpperBound(0);
        UB_Y = mCharBanArr.GetUpperBound(1);

        mIntBanArr = new int[UB_X + 1, UB_Y + 1];
        int IchigoCnt = 1;
        for (int LoopY = 0; LoopY <= UB_Y; LoopY++) {
            for (int LoopX = 0; LoopX <= UB_X; LoopX++) {
                if (mCharBanArr[LoopX, LoopY] == '#') {
                    mIntBanArr[LoopX, LoopY] = IchigoCnt++;
                }
            }
        }

        // 横方向の対応 (0だったら、左をコピー)
        for (int LoopY = 0; LoopY <= UB_Y; LoopY++) {
            for (int LoopX = 1; LoopX <= UB_X; LoopX++) {
                if (mIntBanArr[LoopX, LoopY] == 0) {
                    mIntBanArr[LoopX, LoopY] = mIntBanArr[LoopX - 1, LoopY];
                }
            }
        }

        // 横方向の対応 (0だったら、右をコピー)
        for (int LoopY = 0; LoopY <= UB_Y; LoopY++) {
            for (int LoopX = UB_X - 1; 0 <= LoopX; LoopX--) {
                if (mIntBanArr[LoopX, LoopY] == 0) {
                    mIntBanArr[LoopX, LoopY] = mIntBanArr[LoopX + 1, LoopY];
                }
            }
        }

        // 縦方向の対応1 (行の値が全て0だったら、上の行をコピー)
        for (int LoopY = 1; LoopY <= UB_Y; LoopY++) {
            if (IsAllZero(LoopY) == false) {
                continue;
            }
            for (int LoopX = 0; LoopX <= UB_X; LoopX++) {
                mIntBanArr[LoopX, LoopY] = mIntBanArr[LoopX, LoopY - 1];
            }
        }

        // 縦方向の対応2 (行の値が全て0だったら、下の行をコピー)
        for (int LoopY = UB_Y - 1; 0 <= LoopY; LoopY--) {
            if (IsAllZero(LoopY) == false) {
                continue;
            }
            for (int LoopX = 0; LoopX <= UB_X; LoopX++) {
                mIntBanArr[LoopX, LoopY] = mIntBanArr[LoopX, LoopY + 1];
            }
        }

        PrintBan(mIntBanArr);
    }

    // 配列の指定行が、全て0かを返す
    static bool IsAllZero(int pY)
    {
        for (int LoopX = 0; LoopX <= UB_X; LoopX++) {
            if (mIntBanArr[LoopX, pY] != 0) {
                return false;
            }
        }
        return true;
    }

    ////////////////////////////////////////////////////////////////
    // IEnumerable<string>をcharの2次元配列に設定する
    ////////////////////////////////////////////////////////////////
    static char[,] CreateBanArr(IEnumerable<string> pStrEnum)
    {
        var StrList = pStrEnum.ToList();
        if (StrList.Count == 0) {
            return new char[0, 0];
        }
        int UB_X = StrList[0].Length - 1;
        int UB_Y = StrList.Count - 1;

        char[,] WillReturn = new char[UB_X + 1, UB_Y + 1];

        for (int Y = 0; Y <= UB_Y; Y++) {
            for (int X = 0; X <= UB_X; X++) {
                WillReturn[X, Y] = StrList[Y][X];
            }
        }
        return WillReturn;
    }

    ////////////////////////////////////////////////////////////////
    // 2次元配列(int型)のデバッグ出力
    ////////////////////////////////////////////////////////////////
    static void PrintBan(int[,] pBanArr)
    {
        for (int Y = 0; Y <= pBanArr.GetUpperBound(1); Y++) {
            for (int X = 0; X <= pBanArr.GetUpperBound(0); X++) {
                if (X > 0) {
                    Console.Write(" ");
                }
                Console.Write(pBanArr[X, Y]);
            }
            Console.WriteLine();
        }
    }
}


解説

まず、全ての行にイチゴがある場合を考察します。
010200
000030
0なら左マスをコピーして、盤面は下記になります。
011222
000033
次に0なら右マスをコピーして、盤面は下記になります。
111222
333333
でこれが解になります。

イチゴの無い行がある場合を考えると
000000
000000
010200
000000
000030
000000
000000
行単位で処理すると
000000
000000
111222
000000
333333
000000
000000
イチゴの無い行は、上か下の行の値をコピーすれば
解になると分かります。