結果
問題 | No.428 小数から逃げる夢 |
ユーザー |
![]() |
提出日時 | 2024-10-10 23:56:16 |
言語 | C#(csc) (csc 3.9.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 5,654 bytes |
コンパイル時間 | 1,239 ms |
コンパイル使用メモリ | 117,092 KB |
実行使用メモリ | 26,928 KB |
最終ジャッジ日時 | 2024-10-10 23:56:23 |
合計ジャッジ時間 | 6,838 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | RE * 100 |
コンパイルメッセージ
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以上の数値があったらNofor (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();}}}