結果
問題 | No.228 ゆきこちゃんの 15 パズル |
ユーザー | aketijyuuzou |
提出日時 | 2024-10-10 23:41:35 |
言語 | C#(csc) (csc 3.9.0) |
結果 |
AC
|
実行時間 | 39 ms / 5,000 ms |
コード長 | 5,654 bytes |
コンパイル時間 | 1,003 ms |
コンパイル使用メモリ | 116,592 KB |
実行使用メモリ | 28,632 KB |
最終ジャッジ日時 | 2024-10-10 23:41:37 |
合計ジャッジ時間 | 2,538 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 33 ms
26,288 KB |
testcase_01 | AC | 33 ms
26,552 KB |
testcase_02 | AC | 34 ms
24,624 KB |
testcase_03 | AC | 31 ms
26,304 KB |
testcase_04 | AC | 34 ms
28,632 KB |
testcase_05 | AC | 35 ms
28,388 KB |
testcase_06 | AC | 38 ms
28,372 KB |
testcase_07 | AC | 35 ms
26,428 KB |
testcase_08 | AC | 35 ms
26,428 KB |
testcase_09 | AC | 37 ms
26,592 KB |
testcase_10 | AC | 35 ms
26,428 KB |
testcase_11 | AC | 34 ms
24,628 KB |
testcase_12 | AC | 33 ms
26,452 KB |
testcase_13 | AC | 31 ms
26,560 KB |
testcase_14 | AC | 32 ms
28,336 KB |
testcase_15 | AC | 31 ms
26,684 KB |
testcase_16 | AC | 34 ms
28,468 KB |
testcase_17 | AC | 39 ms
26,684 KB |
testcase_18 | AC | 32 ms
26,292 KB |
testcase_19 | AC | 32 ms
26,428 KB |
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc) Copyright (C) Microsoft Corporation. All rights reserved.
ソースコード
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 4"); WillReturn.Add("5 6 7 8"); WillReturn.Add("9 10 11 12"); WillReturn.Add("13 14 15 0"); //Yes //初期配置がそのまま目標の配置である。 } else if (InputPattern == "Input2") { WillReturn.Add("1 2 3 4"); WillReturn.Add("5 6 7 8"); WillReturn.Add("9 10 12 0"); WillReturn.Add("13 14 11 15"); //Yes } else if (InputPattern == "Input3") { WillReturn.Add("1 2 3 4"); WillReturn.Add("5 6 7 8"); WillReturn.Add("9 10 12 15"); WillReturn.Add("13 14 11 0"); //No //目標の配置を作るためには、15の駒を最低2回はスライドしなければならない。 } else { string wkStr; while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr); } return WillReturn; } const int UB = 4 - 1; static void Main() { List<string> InputList = GetInputList(); int[,] BanArr = new int[UB + 1, UB + 1]; for (int Y = 0; Y <= UB; Y++) { int[] wkArr = InputList[Y].Split(' ').Select(X => int.Parse(X)).ToArray(); for (int X = 0; X <= UB; X++) { BanArr[X, Y] = wkArr[X]; } } Console.WriteLine(HasAnswer(BanArr) ? "Yes" : "No"); } struct JyoutaiDef { internal int[,] BanArr; internal HashSet<int> MovedNumSet; } //深さ優先探索で解を探す static bool HasAnswer(int[,] pBanArr) { //正位置とのマンハッタン距離が2以上の数値があったらNo for (int LoopX = 0; LoopX <= UB; LoopX++) { for (int LoopY = 0; LoopY <= UB; LoopY++) { if (pBanArr[LoopX, LoopY] == 0) continue; if (DeriveKyori(pBanArr[LoopX, LoopY], LoopX, LoopY) >= 2) return false; } } var stk = new Stack<JyoutaiDef>(); JyoutaiDef WillPush; WillPush.BanArr = pBanArr; WillPush.MovedNumSet = new HashSet<int>(); stk.Push(WillPush); while (stk.Count > 0) { JyoutaiDef Popped = stk.Pop(); //PrintBan(Popped.BanArr); //クリア判定 if (IsClear(Popped.BanArr)) return true; int ZeroX, ZeroY; Derive0Zahyou(Popped.BanArr, out ZeroX, out ZeroY); Action<int, int> PushSyori = (pFromX, pFromY) => { if (pFromX < 0 || UB < pFromX) return; if (pFromY < 0 || UB < pFromY) return; //1度移動した数値は移動不可 if (Popped.MovedNumSet.Contains(pBanArr[pFromX, pFromY])) return; //正位置とのマンハッタン距離が1の数値のみ移動可 if (DeriveKyori(pBanArr[pFromX, pFromY], pFromX, pFromY) != 1) return; WillPush.BanArr = (int[,])Popped.BanArr.Clone(); int SankakuWK = WillPush.BanArr[pFromX, pFromY]; WillPush.BanArr[pFromX, pFromY] = 0; WillPush.BanArr[ZeroX, ZeroY] = SankakuWK; WillPush.MovedNumSet = new HashSet<int>(Popped.MovedNumSet) { SankakuWK }; stk.Push(WillPush); }; PushSyori(ZeroX, ZeroY - 1); PushSyori(ZeroX, ZeroY + 1); PushSyori(ZeroX - 1, ZeroY); PushSyori(ZeroX + 1, ZeroY); } return false; } //数値の現座標を引数として、正位置とのマンハッタン距離を求める static int DeriveKyori(int pCurrNum, int pX, int pY) { int NeedNum = 1; for (int LoopY = 0; LoopY <= UB; LoopY++) { for (int LoopX = 0; LoopX <= UB; LoopX++) { if (pCurrNum == NeedNum++) { return Math.Abs(LoopX - pX) + Math.Abs(LoopY - pY); } } } return -1; } //盤面の0の座標を返す static void Derive0Zahyou(int[,] pBanArr, out int pX, out int pY) { pX = pY = -1; for (int LoopX = 0; LoopX <= UB; LoopX++) { for (int LoopY = 0; LoopY <= UB; LoopY++) { if (pBanArr[LoopX, LoopY] != 0) continue; pX = LoopX; pY = LoopY; return; } } } //クリア判定 static bool IsClear(int[,] pBanArr) { int NeedNum = 1; for (int LoopY = 0; LoopY <= UB; LoopY++) { for (int LoopX = 0; LoopX <= UB; LoopX++) { if (LoopX == UB && LoopY == UB) { if (pBanArr[LoopX, LoopY] != 0) return false; } else if (pBanArr[LoopX, LoopY] != NeedNum++) return false; } } return true; } //盤面を表示 static void PrintBan(int[,] pBanArr) { Console.WriteLine(new string('■', 8)); for (int LoopY = 0; LoopY <= UB; LoopY++) { for (int LoopX = 0; LoopX <= UB; LoopX++) { Console.Write("{0,2},", pBanArr[LoopX, LoopY]); } Console.WriteLine(); } } }