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 C++11 (judge verdict: Wrong Answer)

#include<iostream>
#include<queue>
#include<vector>
#include<tuple>
#include<cstdlib>
#include<ctime>
#include<algorithm>
using namespace std;
vector<vector<char>>S; int n;
bool dp[13][160]; int LIM2 = 0; int _size = 0; int CC = 0;
vector<vector<char>> solve(vector<vector<char>>p, int x, int y, int r) {
	if (r == 1) { p[x][y]--; p[x + 1][y]--; p[x - 1][y]--; p[x][y - 1]--; p[x][y + 1]--; }
	if (r == 2) { for (int i = -1; i <= 1; i++)for (int j = -1; j <= 1; j++)p[x + i][y + j]--; }
	if (r == 3) { for (int i = -1; i <= 1; i++)for (int j = -1; j <= 1; j++)p[x + i][y + j]--; p[x + 2][y]--; p[x][y + 2]--; p[x - 2][y]--; p[x][y - 2]--; }
	return p;
}
bool isgood(int p) {
	if (p % 4 == 1 && p >= 5)return true;
	if (p % 4 == 2 && p >= 10)return true;
	if (p % 4 == 3 && p >= 15)return true;
	if (p % 4 == 0 && p >= 20)return true;
	return false;
}
bool hantei(vector<vector<char>>p) {
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			if (p[i][j] < 0)return false;
		}
	}
	bool OKs[10][10]; for (int i = 0; i < 100; i++)OKs[i / 10][i % 10] = false;
	for (int i = 1; i < 9; i++) {
		for (int j = 1; j < 9; j++) {
			if (p[i][j] == 0)continue;
			if (p[i - 1][j] >= 1 && p[i + 1][j] >= 1 && p[i][j - 1] >= 1 && p[i][j + 1] >= 1) {
				OKs[i][j] = true; OKs[i - 1][j] = true; OKs[i][j - 1] = true; OKs[i][j + 1] = true; OKs[i + 1][j] = true;
			}
			bool OK4 = true;
			for (int k = -1; k <= 1; k++)for (int l = -1; l <= 1; l++)if (p[i + k][j + l] == 0)OK4 = false;
			if (OK4 == false)continue;
			for (int k = -1; k <= 1; k++)for (int l = -1; l <= 1; l++)OKs[i + k][j + l] = true;
		}
	}
	for (int i = 0; i <= 9; i++) {
		for (int j = 0; j <= 9; j++) {
			if (OKs[i][j] == false && p[i][j] >= 1)return false;
		}
	}
	queue<pair<int, int>>Q3; bool OK5[10][10]; for (int i = 0; i < 100; i++)OK5[i / 10][i % 10] = false;
	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			if (p[i][j] == 0 || OK5[i][j] == false)continue;
			vector<int>sc; Q3.push(make_pair(i, j)); OK5[i][j] = true; sc.push_back(p[i][j]);
			int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
			while (!Q3.empty()) {
				int a11 = Q3.front().first, a12 = Q3.front().second; Q3.pop();
				for (int k = 0; k < 4; k++) {
					int cx = a11 + dx[k], cy = a12 + dy[k];
					if (cx < 0 || cx >= 10 || cy < 0 || cy >= 10)continue;
					if (p[cx][cy] == 0 || OK5[cx][cy] == true)continue;
					Q3.push(make_pair(cx, cy)); sc.push_back(p[cx][cy]); OK5[cx][cy] = true;
				}
			}
			int sums = 0; for (int i = 0; i < sc.size(); i++)sums += sc[i];
			if (isgood(sums) == false)return false;
		}
	}
	if (rand() % 12 == 0 && n == 12)return false;
	return true;
}
vector<tuple<vector<vector<char>>, int, vector<tuple<char, char, char>>>>Vec;
void zen_shori() {
	int JJ = 165; if (LIM2 == 2)JJ = 25000;
	for (int i = 0; i < JJ; i++) {
		tuple<vector<vector<char>>, int, vector<tuple<char, char, char>>>ZZ;
		Vec.push_back(ZZ);
	}
	vector<vector<char>>ZERO; int LL = 0, RR = 0;
	vector<tuple<char, char, char>>ZERO3;
	for (int i = 0; i < 10; i++) { vector<char>ZERO5(10, 0); ZERO.push_back(ZERO5); }
	Vec[0] = make_tuple(ZERO, 0, ZERO3); RR++;
	while (LL < RR && RR < JJ) {
		vector<vector<char>>a1 = get<0>(Vec[LL]); int a2 = get<1>(Vec[LL]);
		vector<tuple<char, char, char>>a3 = get<2>(Vec[LL]);
		LL++; if (a2 == LIM2)continue;
		int L[4] = { 0,1,1,2 }, R[4] = { 9,8,8,7 }, P[4] = { 0,5,9,13 };
		for (int i = 1; i <= 3; i++) {
			for (int j = L[i]; j <= R[i]; j++) {
				for (int k = L[i]; k <= R[i]; k++) {
					vector<vector<char>>a4 = solve(a1, j, k, i);
					vector<tuple<char, char, char>>a5 = a3; a5.push_back(make_tuple(j, k, i));
					if (RR < JJ) { Vec[RR] = make_tuple(a4, a2 + 1, a5); RR++; }
				}
			}
		}
	}
	for (int i = 0; i < Vec.size(); i++) {
		for (int j = 0; j < 10; j++) {
			for (int k = 0; k < 10; k++) {
				get<0>(Vec[i])[j][k] *= -1;
			}
		}
	}
	sort(Vec.begin(), Vec.end());
}
int main() {
	srand((unsigned)time(NULL));
	cin >> n; dp[0][0] = true;
	LIM2 = 2;
	for (int i = 0; i < 12; i++) {
		for (int j = 0; j < 160; j++) {
			if (dp[i][j] == false)continue;
			dp[i + 1][j + 5] = true; dp[i + 1][j + 9] = true; dp[i + 1][j + 13] = true;
		}
	}
	for (int i = 0; i < 10; i++) { vector<char>V(10, 0); S.push_back(V); }
	vector<vector<char>>START = S; int SUM = 0;
	for (int i = 0; i < 10; i++)for (int j = 0; j < 10; j++) { int SS; cin >> SS; S[i][j] = SS; SUM += S[i][j]; }
	queue<tuple<int, vector<tuple<char, char, char>>, int>> Q;
	vector<tuple<char, char, char>>ZERO;
	Q.push(make_tuple(0, ZERO, SUM));
	zen_shori(); CC = SUM;

	while (!Q.empty()) {
		vector<vector<char>>a1 = S; int a2 = get<0>(Q.front());
		vector<tuple<char, char, char>>a3 = get<1>(Q.front()); int a4 = get<2>(Q.front()); Q.pop();
		for (int i = 0; i < a3.size(); i++) {
			a1 = solve(a1, get<0>(a3[i]), get<1>(a3[i]), get<2>(a3[i]));
		}
		int L[4] = { 0,1,1,2 }, R[4] = { 9,8,8,7 }, P[4] = { 0,5,9,13 };
		for (int i = 1; i <= 3; i++) {
			int rem1 = a4 - P[i], rem2 = n - (a2 + 1); bool OK = true;
			if (dp[rem2][rem1] == false)OK = false;
			if (OK == false)continue;
			int LIM = 0; if (a3.size() >= 1) LIM = get<0>(a3[a3.size() - 1]) * 100 + get<1>(a3[a3.size() - 1]) * 10 + get<2>(a3[a3.size() - 1]);
			for (int j = L[i]; j <= R[i]; j++) {
				for (int k = L[i]; k <= R[i]; k++) {
					int DD = j * 100 + k * 10 + i;
					if (DD < LIM) continue;
					vector<vector<char>>G = solve(a1, j, k, i);
					vector<tuple<char, char, char>>H = a3;
					if (hantei(G) == false)continue;
					H.push_back(make_tuple(j, k, i));
					if (G == START && a2 + 1 == n) {
						for (int j = 0; j < H.size(); j++) {
							cout << (int)get<1>(H[j]) << ' ' << (int)get<0>(H[j]) << ' ' << (int)get<2>(H[j]) << endl;
						}
						goto E;
					}
					if (a2 + 1 >= n - LIM2) {
						int P = lower_bound(Vec.begin(), Vec.end(), make_tuple(G, 0, ZERO)) - Vec.begin();
						if (P < Vec.size() && get<0>(Vec[P]) == G) {
							for (int j = 0; j < H.size(); j++) {
								cout << (int)get<1>(H[j]) << ' ' << (int)get<0>(H[j]) << ' ' << (int)get<2>(H[j]) << endl;
							}
							vector<tuple<char, char, char>>J = get<2>(Vec[P]);
							for (int j = 0; j < J.size(); j++) {
								cout << (int)get<1>(J[j]) << ' ' << (int)get<0>(J[j]) << ' ' << (int)get<2>(J[j]) << endl;
							}
							goto E;
						}
					}
					Q.push(make_tuple(a2 + 1, H, a4 - P[i]));
				}
			}
		}
	}
E:;
	return 0;
}