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.awt.geom.Point2D;
import java.io.*;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.PriorityQueue;
import java.util.Scanner;

import javax.xml.crypto.Data;
public class Main {
	static boolean[] ans;
	static int[][] pass;
	static PrintWriter out = new PrintWriter(System.out);
	static FastScanner sc = new FastScanner();
	static int[][] map;
	static int n;
	
	static HashSet<ArrayList<Data>> set = new HashSet<ArrayList<Data>>();
	public static void main(String[] args) {
		n = sc.nextInt();
		map = new int[10][10];
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				map[i][j] = sc.nextInt();
			}
		}
		ansX.add( new ArrayList<Data>());
		solv(1,1,0);
		
		out.flush();

	}
	
	
	static ArrayDeque<ArrayList<Data>> ansX = new ArrayDeque<ArrayList<Data>>();
	static int[][] mapx = new int[10][10];
	static boolean check(ArrayList<Data> a) {
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				mapx[i][j] = 0;
			}
		}
		int maxy = -1;
		for(int i = 0; i < a.size(); i++) {
			Data tmp = a.get(i);
			int x = tmp.x;
			int y = tmp.y;
			if(y > maxy) maxy = y;
			if(tmp.size == 1) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
			}
			if(tmp.size == 2) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
				mapx[y+1][x+1]++;
				mapx[y+1][x-1]++;
				mapx[y-1][x+1]++;
				mapx[y-1][x-1]++;
			}
			if(tmp.size == 3) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
				mapx[y+1][x+1]++;
				mapx[y+1][x-1]++;
				mapx[y-1][x+1]++;
				mapx[y-1][x-1]++;
				mapx[y-2][x]++;
				mapx[y+2][x]++;
				mapx[y][x+2]++;
				mapx[y][x-2]++;
			}
			
			
		}
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				if(mapx[i][j] > map[i][j]) return false;
				if(maxy - 3 >= 0 && i <= maxy - 3 && mapx[i][j] != map[i][j]) return false;
			}
		}
		return true;
	}
	static boolean clear(ArrayList<Data> a) {
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				mapx[i][j] = 0;
			}
		}
		for(int i = 0; i < a.size(); i++) {
			Data tmp = a.get(i);
			int x = tmp.x;
			int y = tmp.y;
			if(tmp.size == 1) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
			}
			if(tmp.size == 2) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
				mapx[y+1][x+1]++;
				mapx[y+1][x-1]++;
				mapx[y-1][x+1]++;
				mapx[y-1][x-1]++;
			}
			if(tmp.size == 3) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
				mapx[y+1][x+1]++;
				mapx[y+1][x-1]++;
				mapx[y-1][x+1]++;
				mapx[y-1][x-1]++;
				mapx[y-2][x]++;
				mapx[y+2][x]++;
				mapx[y][x+2]++;
				mapx[y][x-2]++;
			}
			
			
		}
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				if(mapx[i][j] != map[i][j]) return false;
			}
		}
		return true;
	}
	
	static void show(ArrayList<Data> a) {
		for(int i = 0; i < a.size(); i++) {
			out.println(a.get(i).x + " " + a.get(i).y + " " + a.get(i).size);
		}
	}
	static void showX(ArrayList<Data> a) {
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				mapx[i][j] = 0;
			}
		}
		for(int i = 0; i < a.size(); i++) {
			Data tmp = a.get(i);
			int x = tmp.x;
			int y = tmp.y;
			if(tmp.size == 1) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
			}
			if(tmp.size == 2) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
				mapx[y+1][x+1]++;
				mapx[y+1][x-1]++;
				mapx[y-1][x+1]++;
				mapx[y-1][x-1]++;
			}
			if(tmp.size == 3) {
				mapx[y][x]++;
				mapx[y-1][x]++;
				mapx[y+1][x]++;
				mapx[y][x+1]++;
				mapx[y][x-1]++;
				mapx[y+1][x+1]++;
				mapx[y+1][x-1]++;
				mapx[y-1][x+1]++;
				mapx[y-1][x-1]++;
				mapx[y-2][x]++;
				mapx[y+2][x]++;
				mapx[y][x+2]++;
				mapx[y][x-2]++;
			}
			
			
		}
		for(int i = 0; i < 10; i++) {
			for(int j = 0; j < 10; j++) {
				System.out.print(mapx[i][j] + " ");
			}
			System.out.println();
		}
		System.out.println("==");
	}
	static boolean isOKA(int x, int y,int c) {
		if(x-1 < 0 || y-1 < 0 || x+1 >= 10 || y+1 >= 10 || ansX.isEmpty() || c > n) return false;
		return true;
	}
	
	static boolean isOKB(int x, int y,int c) {
		if(x-2 < 0 || y-2 < 0 || x+2 >= 10 || y+2 >= 10 || ansX.isEmpty() || c > n) return false;
		return true;
	}
	static void solv(int xd, int yd, int count) {
		if(xd == 9) {
			xd = 1;
			yd++;
		}
		
		if(xd >= 9 || yd >= 9) return;
		if(ansX.isEmpty()) return;

		if(xd == 9) {
			xd = 0;
			yd++;
		}
		
		ArrayList<Data> a = ansX.getFirst();
		if(n == count && clear(a)) {
			show(a);
			ansX.clear();
			return;
		}
		
		if(n == count){
			return;
		}
		
		ansX.addFirst(a);
		solv(xd+1,yd,count);
	
		if(isOKA(xd,yd,count+1)) {
			ArrayList<Data> b = new ArrayList<Data>(a);
			b.add(new Data(xd,yd,1));
			if(check(b)) {
				ansX.addFirst(b);
				solv(xd,yd,count+1);
			}
			if(!ansX.isEmpty()) {
			b = new ArrayList<Data>(a);
			b.add(new Data(xd,yd,2));
			if(check(b)) {
				ansX.addFirst(b);
				solv(xd,yd,count+1);
			}
			}
		}

		if(isOKB(xd,yd,count+1)) {
			ArrayList<Data> b = new ArrayList<Data>(a);
			b.add(new Data(xd,yd,3));
			if(check(b)) {
				ansX.addFirst(b);
				solv(xd,yd,count+1);
			}
		}
		
		
		
	}
	
	static class Data {
		int x;
		int y;
		int size;
		Data(int a, int b, int c) {
			x = a;
			y = b;
			size = c;
		}
	}

}


		
//------------------------------//
//-----------//
class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    private void skipUnprintable() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++;}
    public boolean hasNext() { skipUnprintable(); return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    
    public int nextInt() {
    	return (int)nextLong();
    }
    
    public double nextDouble() {
    	return Double.parseDouble(next());
    }
    

}