using System; using System.Collections.Generic; using System.Linq; class Program { static string InputPattern = "InputX"; static List GetInputList() { var WillReturn = new List(); if (InputPattern == "Input1") { WillReturn.Add("5 5"); WillReturn.Add("0 0 1 1 1"); WillReturn.Add("0 0 1 1 1"); WillReturn.Add("1 1 0 1 1"); WillReturn.Add("1 1 1 0 0"); WillReturn.Add("1 1 1 0 0"); //2 } else if (InputPattern == "Input2") { WillReturn.Add("4 4"); WillReturn.Add("0 0 0 0"); WillReturn.Add("0 1 1 0"); WillReturn.Add("0 1 1 0"); WillReturn.Add("0 0 0 0"); //16 } else if (InputPattern == "Input3") { WillReturn.Add("8 5"); WillReturn.Add("0 0 1 1 1"); WillReturn.Add("0 0 1 1 1"); WillReturn.Add("0 1 0 0 1"); WillReturn.Add("1 0 0 1 0"); WillReturn.Add("1 1 1 0 0"); WillReturn.Add("1 0 1 0 1"); WillReturn.Add("0 1 0 0 1"); WillReturn.Add("0 0 1 1 1"); //5 } else { string wkStr; while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr); } return WillReturn; } static int UB_X; static int UB_Y; struct JyoutaiDef { internal int CurrX; internal int CurrY; internal int Cost; internal bool[,] MasuArr; } static void Main() { List InputList = GetInputList(); int[] wkArr = { }; Action SplitAct = pStr => wkArr = pStr.Split(' ').Select(X => int.Parse(X)).ToArray(); SplitAct(InputList[0]); int M = wkArr[0], N = wkArr[1]; UB_X = N - 1; UB_Y = M - 1; bool[,] mQuestionArr = new bool[UB_X + 1, UB_Y + 1]; for (int I = 1; I <= InputList.Count - 1; I++) { SplitAct(InputList[I]); for (int J = 0; J <= wkArr.GetUpperBound(0); J++) { mQuestionArr[J, I - 1] = (wkArr[J] == 1); } } var Stk = new Stack(); JyoutaiDef WillPush; WillPush.CurrX = WillPush.CurrY = 0; WillPush.Cost = 0; WillPush.MasuArr = mQuestionArr; Stk.Push(WillPush); int AnswerCost = int.MaxValue; bool FoundAnswer = false; while (Stk.Count > 0) { JyoutaiDef Popped = Stk.Pop(); if (IsOK(Popped.MasuArr)) { FoundAnswer = true; AnswerCost = Popped.Cost; continue; } //下限値枝切り if (AnswerCost <= Popped.Cost) continue; if (Popped.CurrY == UB_Y + 1) { continue; } //次の座標を設定 WillPush.CurrY = Popped.CurrY; WillPush.CurrX = Popped.CurrX + 1; if (WillPush.CurrX == UB_X + 1) { WillPush.CurrY++; WillPush.CurrX = 0; } bool WillPushHanten = false; //反転させるケース bool WillPushNonHanten = false; //反転させないケース if (Popped.CurrY == 0) { //Y座標が0の場合 WillPushHanten = WillPushNonHanten = true; } else { //Y座標が1以上の場合 var wkList = new List(); //X=UB_Xなら、真上と左上 if (Popped.CurrX == UB_X) { wkList.AddRange(DeriveBoolList(Popped.MasuArr, Popped.CurrX, Popped.CurrY - 1)); wkList.AddRange(DeriveBoolList(Popped.MasuArr, Popped.CurrX - 1, Popped.CurrY - 1)); } else { //X A)) { //全部1の場合 WillPushHanten = true; } else if (wkList.TrueForAll(A => A == false)) { //全部0の場合 WillPushNonHanten = true; } } if (WillPushHanten) { //反転させるケースをPush WillPush.Cost = Popped.Cost + 1; WillPush.MasuArr = (bool[,])Popped.MasuArr.Clone(); HantenSyori(WillPush.MasuArr, Popped.CurrX, Popped.CurrY); Stk.Push(WillPush); } if (WillPushNonHanten) { //反転させないケースをPush WillPush.Cost = Popped.Cost; WillPush.MasuArr = Popped.MasuArr; Stk.Push(WillPush); } } if (FoundAnswer) Console.WriteLine(AnswerCost); else Console.WriteLine("Impossible"); } //終了判定 static bool IsOK(bool[,] pMasuArr) { foreach (bool EachBool in pMasuArr) { if (EachBool) return false; } return true; } //指定した座標のBool型のListを返す static List DeriveBoolList(bool[,] pMasuArr, int pX, int pY) { if (pX < 0 || UB_X < pX) return new List(); if (pY < 0 || UB_Y < pY) return new List(); return new List() { pMasuArr[pX, pY] }; } //押したマスと8近傍の、座標を反転 static void HantenSyori(bool[,] pMasuArr, int pX, int pY) { MasuHanten(pMasuArr, pX - 1, pY - 1); MasuHanten(pMasuArr, pX - 1, pY); MasuHanten(pMasuArr, pX - 1, pY + 1); MasuHanten(pMasuArr, pX, pY - 1); MasuHanten(pMasuArr, pX, pY); MasuHanten(pMasuArr, pX, pY + 1); MasuHanten(pMasuArr, pX + 1, pY - 1); MasuHanten(pMasuArr, pX + 1, pY); MasuHanten(pMasuArr, pX + 1, pY + 1); } //指定マスの0と1の反転 static void MasuHanten(bool[,] pMasuArr, int pX, int pY) { if (pX < 0 || UB_X < pX) return; if (pY < 0 || UB_Y < pY) return; pMasuArr[pX, pY] = !pMasuArr[pX, pY]; } }