Problem:
あみだくじ II

縦線が n 本のあみだくじがあります。このあみだくじは以下の条件を満たしています。

横線は真横に引きます。斜めに引くことはありません。

横線は必ず隣り合った縦線同士をつなぎます。つまり、横線が縦線をまたぐことはありません。

どの縦線についても同じ点から左右同時に横線が出ることはありません。つまり、横線が縦線を横切ることはありません。

当りはひとつだけです。

下図 に n = 5 のときの、あみだくじの例を示します。上側の数字は縦線の番号(左から1, 2, 3, 4, 5 ) を表します。☆が当たりです。

縦線の本数 n、選んだ縦線の番号 m、あみだくじの当りの場所、各段における横線の有無を読み込んで、当りにたどり着けるかどうかの判定を出力するプログラムを作成してください。ただし、与えられたあみだくじの任意の位置に1 本だけ横線を付け加えることができるものとします（付け加えなくてもかまいません）。横線を1 本付け加えた後のあみだくじも前述の条件を満たしていなければなりません。

Input

複数のデータセットが与えられます。各データセットは以下のとおりです：

１行目に、縦線の本数 n (1 < n ≤ 10) が書かれています。

２行目には、選んだ縦線の番号 m (1 ≤ m ≤ n) が書かれています。

３行目には、当りの場所（図でいう☆）が左から数えて何番目かが書かれています。

４行目には、あみだくじの段数 d (1 ≤ d ≤ 30) が書かれています。

５行目以降は、図に対応する数字の並びのように、あみだくじの上から順に、各縦線の間に横線があるときを 1、ないときを 0 として、n - 1 つの数字が並んでいます。

入力は１つの 0 が書かれた行で終わります。

Output

各データセットについて、選んだ縦線の番号 m から当りにたどり着けるかどうかに応じて以下の値を出力してください。

横線を引かなくても当りにたどり着けるときは 0 を出力してください。

横線を1 本引けば当りにたどり着けるときは、その中で最も出発側（図でみて上）に近い横線の位置を出力してください。出発側から数えて何段目（図 を参考にしてください）に、左から数えて何番目の縦線から右に向かって横線を引くかを半角の空白で区切って出力してください。

横線を1 本引いても当りにたどり着けないときには 1 を出力してください。

Sample Input

5
2
3
9
1010
1001
0100
1001
0010
1000
0100
0101
1010
0

Output for the Sample Input

6 4

Solution in C# (judge verdict: Accepted)

using System;

namespace _069_DrawingLotsII
{
	class Program
	{
		static void Main ( string[] args )
		{
			string inputStr;

			while ((inputStr = Console.ReadLine ()) != "0")
			{
				//input
				int lineCount = int.Parse (inputStr);
				int startNumber = int.Parse (Console.ReadLine ());
				int hitNumber = int.Parse (Console.ReadLine ());
				int stageNumber = int.Parse (Console.ReadLine ());
				string[] map = new string[stageNumber];
				for (int lp = 0; lp < stageNumber; lp++)
				{
					map[lp] = Console.ReadLine ();
				}

				//process
				Solve.SetData (lineCount, startNumber, hitNumber, stageNumber, map);
				var result = Solve.Result ();
				Console.WriteLine (result);
			}
		}

		static class Solve
		{
			private static int LineCount { set; get; }
			private static int StartNumber { set; get; }
			private static int HitNumber { set; get; }
			private static int StageNumber { set; get; }
			private static char[][] Map { set; get; }
			const char Exist = '1';
			const char NotExist = '0';

			private static int[] PositionMemory { set; get; }

			public static void SetData ( int lineCount, int startNumber, int hitNumber, int stageCount, string[] map )
			{
				//copy
				LineCount = lineCount;
				StartNumber = startNumber - 1;
				HitNumber = hitNumber - 1;
				StageNumber = stageCount;
				Map = new char[stageCount][];
				for (int lp = 0; lp < Map.Length; lp++)
				{
					Map[lp] = map[lp].ToCharArray ();
				}
			}

			public static string Result ()
			{
				//process
				PositionMemory = new int[StageNumber];

				//????????????????????????
				if (IsHit2 () || LineCount == 1)
				{
					return "0";
				}

				for (int height = 0; height < StageNumber; height++)
				{
					if (IsLeft (height))
					{
						return (height + 1) + " " + (PositionMemory[height]);
					}
					else if (IsRight (height))
					{
						return (height + 1) + " " + (PositionMemory[height] + 1);
					}
				}

				return "1";
			}

			private static bool IsLeft ( int height )
			{
				//1??¬??????
				int changePoint = PositionMemory[height];

				bool isLeft = 0 <= changePoint - 1;

				//????????????map??????????????????IsHit???????????????

				if (isLeft)
				{
					if (Map[height][changePoint - 1] == NotExist)
					{
						//2?????£?¶???§?????°?????????????????????
						//???????????¨?????????
						if (0 <= changePoint - 2)
						{
							if (Map[height][changePoint - 2] == Exist)
							{
								return false;
							}
						}

						//???????????¨?????????
						if (changePoint < Map[height].Length)
						{
							if (Map[height][changePoint] == Exist)
							{
								return false;
							}
						}

						Map[height][changePoint - 1] = Exist;
						bool result = IsHit ();
						Map[height][changePoint - 1] = NotExist;
						return result;
					}
				}

				return false;
			}

			private static bool IsRight ( int height )
			{
				//1??¬??????
				int changePoint = PositionMemory[height];

				bool isRight = changePoint < Map[height].Length;

				//????????????map??????????????????IsHit???????????????

				if (isRight)
				{
					if (Map[height][changePoint] == NotExist)
					{
						//2?????£?¶???§?????°?????????????????????

						//???????????¨?????????
						if (0 <= changePoint - 1)
						{
							if (Map[height][changePoint - 1] == Exist)
							{
								return false;
							}
						}

						//???????????¨?????????
						if (changePoint + 1 < Map[height].Length)
						{
							if (Map[height][changePoint + 1] == Exist)
							{
								return false;
							}
						}

						Map[height][changePoint] = Exist;
						bool result = IsHit ();
						Map[height][changePoint] = NotExist;
						return result;
					}
				}

				return false;
			}

			private static bool IsHit ()
			{
				int position = StartNumber;

				for (int height = 0; height < StageNumber; height++)
				{
					bool isThrough = false;

					//????????????
					if (0 <= position - 1)
					{
						if (Map[height][position - 1] == Exist)
						{
							position--;
							isThrough = true;
						}
					}
					//????????????
					if (position < Map[height].Length && !isThrough)
					{
						if (Map[height][position] == Exist)
						{
							position++;
						}
					}
				}

				return position == HitNumber;
			}

			private static bool IsHit2 ()
			{
				int position = StartNumber;

				for (int height = 0; height < StageNumber; height++)
				{
					bool isThrough = false;

					//????????????
					if (0 <= position - 1)
					{
						if (Map[height][position - 1] == Exist)
						{
							position--;
							isThrough = true;
						}
					}
					//????????????
					if (position < Map[height].Length && !isThrough)
					{
						if (Map[height][position] == Exist)
						{
							position++;
						}
					}

					PositionMemory[height] = position;
				}

				return position == HitNumber;
			}
		}
	}
}