Problem:
すごろくを作る

太郎君は、子供会の催しでみんなで遊べるようにすごろくを作りました。ゲームをおもしろくするために、「ふりだし」と「あがり」以外のすごろくのマスのいくつかに「６つ進む」、「５つ戻る」のように指示を書き込んでいきました。ルーレットを回して出た数だけ進み、止まったマスに指示が書き込んであれば、その指示に従って移動します。ただし、指示に従って進んだ先のマスの指示には従いません。

ルーレットは１からある数までの間の数を等確率で出すことができるものとします。また、「あがり」に達するより大きな数が出たときや、指示に従うと「あがり」より先に進んでしまうときは「あがり」に移動します。指示に従って戻るときに「ふりだし」より前に戻ってしまうときは「ふりだし」に戻ることにします。

ところが、ルーレットとマスの指示によっては「あがり」にたどりつけない場合が出てきてしまいます。たとえば、図のようなすごろくを作ったとしましょう。１と２しか出ないルーレットを使うと、１，２の順に出れば「あがり」に行けますが、はじめに２が出たらその後は何が出ても永久に「あがり」にはたどり着けません。太郎君は、そうとは知らずに調子に乗ってあちこちのマスに指示を書き込んでしまいました。

そこで、太郎君に代わって、ルーレットとマスの指示によっては、「あがり」にたどり着けない場合が生じるかどうか判定するプログラムを作成してください。

入力

入力は複数のデータセットからなる。入力の終わりはゼロ１つの行で示される。各データセットは以下の形式で与えられる。

max
n
d1
d2
.
.
.
dn

１行目にルーレットが出す数の最大値 max (2 ≤ max ≤ 250) が与えられ、２行目に「ふりだし」と「あがり」以外のマスの数 n (2 ≤ n ≤ 250) が与えられる。続く n 行に各マスの指示を表す数 di(-n ≤ di ≤ n) が与えられる。di がゼロのときは指示が書いていないことを、正の数のときは |di| 進む指示を、負の数のときは |di| 戻る指示を表す（ここで、|x| は x の絶対値を表す）。入力される値はすべて整数である。

データセットの数は 100 を超えない。

出力

各データセットごとに判定結果を１行に出力する。ルーレットとマスの指示によっては、「あがり」にたどり着けない場合が生じるときは「NG」、そうでなければ「OK」を出力する。

入力例

3
3
-2
1
0
2
4
2
0
-1
-2
2
2
-2
-2
0

出力例

OK
NG
NG

Solution in C# (judge verdict: Accepted)

using System.Collections.Generic;
using System;

public class hello
{
	public static void Main()
	{
		while (true)
		{
			var max = int.Parse(Console.ReadLine().Trim());
			if (max == 0) break;
			var n = int.Parse(Console.ReadLine().Trim());
			var s = new int[n + 2];
			for (int i = 0; i < n; i++)
				s[i + 1] = int.Parse(Console.ReadLine().Trim());
			var aa = setEdge(s, max, n);
			var dp = setDp(aa);
			goWarshall(dp);
			Console.WriteLine(getAns(dp) ? "OK" : "NG");
		}
	}
	static bool getAns(bool[,] dp)
	{
		var a = dp.GetLength(0);
		if (!dp[0, a - 1] ) return false;
		for (int i = 1; i < a - 1; i++)
			if (dp[0, i]  && !dp[i, a - 1] ) return false;
		return true;
	}
	static bool[,] setDp(List<int>[] aa)
	{
		var n = aa.Length;
		var dp = new bool[n + 1, n + 1];
		for (int i = 0; i < n; i++)
		{
			foreach (var x in aa[i])
				dp[i, x] = true;
		}
		for (int i = 0; i < n + 1; i++) dp[i, i] = true;
		return dp;
	}
	static List<int>[] setEdge(int[] s, int max, int n)
	{
		var aa = new List<int>[n + 1];
		for (int i = 0; i < n + 1; i++) aa[i] = new List<int>();
		for (int i = 0; i <= n; i++)
			for (int j = 1; j <= max; j++)
			{
				if (i + j <= n + 1)
				{
					var cmd = s[i + j];
					var np = i + j + cmd;
					if (np > n + 1) np = n + 1;
					if (np < 0) np = 0;
					if (!aa[i].Contains(np)) aa[i].Add(np);
				}
			}
		return aa;
	}
	public static void goWarshall(bool[,] dp)
	{
		var n = dp.GetLength(0);
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				for (int k = 0; k < n; k++)
					if (dp[j, i] && dp[i, k]) dp[j, k] = true;
	}
}