Problem:
Blur

図 1 のような 10×10 のマス目の「布」があり、（1，2）のようにX座標・Y座標の値の対でマス目を示すことにします。座標値は 0 から始まる整数とします。例えば、図 1 の◎の座標は (1, 2) です。
この「布」に染料を少しずつたらして染物を作ります。たらす染料の滴には「大」「中」「小」の 3 サイズがあり、染料の滴の落ちたマス目を中心に図 1 のように周囲も色がつきます。図 1 で☆が中心、○が色のにじむ範囲です。

「布」は、最初は「まっしろ」つまり、どのマス目も色の濃さを示す値が 0 とします。染料の滴が落ちるごとに値が 1 ずつ増えていきます。「小」が（1, 2）、「中」が（3, 2）に落ちた場合、各マス目の値は図 2 の左のようになります。染料がもったいないので、図 2 の右に示すようなにじむ範囲が布の外にはみ出すような染料の落とし方はしないことになっています。また、同じ場所に複数の染料をたらすこともあります。

このような作業を何回か繰り返した結果、布にすばらしい模様が浮かび上がりましたが、残念なことに、うっかり作業経過を記録し忘れてしまいました。どうにもさっぱり思い出せませんが、かろうじて、落とした染料の滴数は覚えていました。あなたは、すばらしい染物を再現しなければなりません。すばらしい染物のデータを読みこんで、どこに、どのような染料をたらしたかを出力するプログラムを作成してください。なお、落とした染料の滴数は 12 以下とします。

入力

入力の形式は以下のとおりです：

最初の 1 行に落とした染料の滴数 n が与えられます。次の行から 10 行に各座標の色の濃さが空白区切りで与えられます。

出力

出力は n 行からなります。染料の滴の「大」を 3、「中」を 2、「小」を 1 で表し、落とした染料ごとに、そのX座標、Y座標、滴の大きさを空白で区切って1行に出力してください。

染料のたらし方はどのような順番で出力しても良いものとします。

入力例1

2
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0
0 0 0 1 0 0 0 1 1 1
0 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

出力例1

3 2 1
8 4 2

入力例2

6
0 0 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
1 1 1 1 1 1 1 1 0 0
0 1 1 1 1 1 1 1 0 0
0 0 1 1 1 3 1 1 0 0
0 0 1 1 3 1 1 1 0 0
0 0 1 1 1 1 1 1 1 0
0 0 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 1 0 0

出力例2

2 2 3
7 7 3
6 3 2
3 6 2
4 4 1
5 5 1

Solution in JAVA (judge verdict: Memory Limit Exceeded)

import java.util.Stack;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.Comparator;

class CompArray implements Comparator<State>
{
	public int compare(State a, State b){
		if( a.n != b.n ) {
			if( a.n < b.n ) {
				return -1;
			}
			if( a.n > b.n ) {
				return 1;
			}
		}
		for(int i = 0; i < a.t.length; ++i){
			for(int j = 0; j < a.t[i].length; ++j){
				if( a.t[i][j] != b.t[i][j] ){
					if( a.t[i][j] < b.t[i][j] ) {
						return -1;
					}
					return 1;
				}
			}
		}
		return 0;
	}
}

class State {
	public Integer n;
	public Integer [][] t = new Integer[10][10];
	
	public String toString(){
		String ret = "" + n +";";
		for(int i = 0; i < t.length; ++i){
			for(int j = 0; j < t[i].length; ++j){
				ret += t[i][j] + " ";
			}
		}
		return ret;
	}
}

class Sheet
{
	private State state;
	private Stack<String> st = new Stack<String>();
	
	private final static int[][][] inkPos = 
	{
		{
			{-1, 0} , {1, 0} , {0,-1} , {0, 1}, {0,0}
		},
		{
			{-1,-1} , {-1,1} , {1,-1} , {1, 1}
		},
		{
			{-2, 0} , {0, 2} , {2, 0} , {0,-2}
		}
	};
	
	
	private boolean isInside(int i, int j)
	{
		return i<10 && j<10 && i>=0 && j>=0;
	}
	
	private boolean droppable(int ink, int i, int j)
	{
		for(int a = 0; a <= ink; ++a) {
			for(int[] r : inkPos[a]) {
				int ci = i + r[0];
				int cj = j + r[1];
				
				if( !isInside(ci,cj) ){
					return false;
					//continue;
				}
				
				if( state.t[ci][cj] < 1 ) {
					return false;
				}
			}
		}
		return true;
	}
	
	private void operateInk(int ink, int i, int j, int op)
	{
		for(int a = 0; a <= ink; ++a) {
			for(int[] r : inkPos[a] ) {
				int ci = i + r[0];
				int cj = j + r[1];
				
				if( op == 0 ) {
					state.t[ci][cj]--;
				} else {
					state.t[ci][cj]++;
				}
			}
		}
	}
	static int cnt = 0;
	
	TreeSet<String> visited = new TreeSet<String>();
	//new CompArray());
	
	public void solve()
	{
		// System.out.println(visited);
		if( !visited.contains(this.state.toString()) ){
			visited.add(this.state.toString());
		} else {
			// System.out.println("skipped");
			return ;
		}
		
		if( state.n == 0 ){
			for(int i = 0; i < state.t.length; ++i) {
				for(int j = 0; j < state.t[i].length; ++j) {
					if( state.t[i][j] != 0 ) {
						return ;
					}
				}
			}
			while( !st.empty() ) {
				System.out.println(st.pop());
			}
		}else{
			
			int minVal = 13;
			for(int i = 0; i < state.t.length; ++i){
				for(int j = 0; j < state.t.length; ++j){
					
					// if( state.t[i][j] > 0 && state.t[i][j] < minVal ) minVal = t[i][j];
					
					if( state.t[i][j] > 0 ) {
						boolean ret = false;

						for(int a = 0; a <= 2; ++a){
							for(int[] r : inkPos[a]){
								int ci = i+r[0];
								int cj = j+r[1];

								if( droppable(a,ci,cj) ){
									ret = true;
								}
							}
						}
						
						if( !ret ) {
							return ;
						}
					}
				}
			}

			// System.out.println(minVal);
			
			// 0 : small -> 2 : large
			for(int a = 2; a >= 0; --a){
				for(int i = a==0?1:a; i < state.t.length-(a==0?1:a); ++i){
					for(int j = a==0?1:a; j < state.t[i].length-(a==0?1:a); ++j){
						
						//if( t[i][j] != minVal ) continue;
						
						if( droppable(a,i,j) ){
							
							// progress state
							--state.n;
							
							operateInk(a,i,j,0);
							
							/*
							System.out.println(n + " " + a + " " + i + " " + j);
							
							for(int ii = 0; ii < 10; ++ii){
								for(int jj = 0; jj < 10; ++jj){
									System.out.print(t[ii][jj] + " ");
								}
								System.out.println();
							}
							*/
							
							st.push(j+" "+i+" "+(a+1));

							solve();
							if( st.empty() ) return ;
						
							
							// rollback state
							++state.n;
							st.pop();
							operateInk(a,i,j,1);
						}
					}
				}
			}
		}
	}
	
	public void input()
	{
		state = new State();
		Scanner sc = new Scanner(System.in);
		
		state.n = sc.nextInt();
		for(Integer[] f : state.t) {
			for(int i = 0; i < f.length; ++i){
				f[i] = sc.nextInt();
			}
		}
	}
}

class Main
{
	public static void main(String [] args)
	{
		Sheet sheet = new Sheet();
		sheet.input();
		sheet.solve();
	}
	
}