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: Accepted)

import java.io.*;
      
class Main{
static int[] sx={0,0,1,0,-1};
static int[] sy={0,1,0,-1,0};
static int[] mx={0,0,1,0,-1,-1,-1,1,1};
static int[] my={0,1,0,-1,0,-1,1,-1,1};
static int[] lx={0,0,1,0,-1,-1,-1,1,1,0,2,0,-2};
static int[] ly={0,1,0,-1,0,-1,1,-1,1,2,0,-2,0};
static int total;
static int res;
static int[][] map=new int[10][10];
static int[][][] drop=new int[10][10][3];
static void sd(int x,int y){
for(int i=0;i<sx.length;i++){
map[x+sx[i]][y+sy[i]]--;
}
total-=5;
res--;
}
static void sr(int x,int y){
for(int i=0;i<sx.length;i++){
map[x+sx[i]][y+sy[i]]++;
}
total+=5;
res++;
}
static boolean scd(int x,int y){
for(int i=0;i<sx.length;i++){
int nx=x+sx[i];
int ny=y+sy[i];
if(nx<0||ny<0||nx>=10||ny>=10||map[nx][ny]==0){
return false;
}
}
return true;
}
static void md(int x,int y){
for(int i=0;i<mx.length;i++){
map[x+mx[i]][y+my[i]]--;
}
total-=9;
res--;
}
static void mr(int x,int y){
for(int i=0;i<mx.length;i++){
map[x+mx[i]][y+my[i]]++;
}
total+=9;
res++;
}
static boolean mcd(int x,int y){
for(int i=0;i<mx.length;i++){
int nx=x+mx[i];
int ny=y+my[i];
if(nx<0||ny<0||nx>=10||ny>=10||map[nx][ny]==0){
return false;
}
}
return true;
}
static void ld(int x,int y){
for(int i=0;i<lx.length;i++){
map[x+lx[i]][y+ly[i]]--;
}
total-=13;
res--;
}
static void lr(int x,int y){
for(int i=0;i<lx.length;i++){
map[x+lx[i]][y+ly[i]]++;
}
total+=13;
res++;
}
static boolean lcd(int x,int y){
for(int i=0;i<lx.length;i++){
int nx=x+lx[i];
int ny=y+ly[i];
if(nx<0||ny<0||nx>=10||ny>=10||map[nx][ny]==0){
return false;
}
}
return true;
}
public static void main(String[] args) throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
res=Integer.parseInt(br.readLine());
total=0;
for(int i=0;i<10;i++){
String[] value=br.readLine().split(" ");
for(int j=0;j<10;j++){
int num=Integer.parseInt(value[j]);
map[i][j]=num;
total+=num;
}
}
if(search(1,1,3)){
for(int i=1;i<9;i++){
for(int j=1;j<9;j++){
for(int k=0;k<3;k++){
if(drop[i][j][k]!=0){
for(int l=0;l<drop[i][j][k];l++){
int m=k+1;
System.out.println(j+" "+i+" "+m);
}
}
}
}
}
}
}
static boolean searchnext(int x,int y){
if(y==8){
return search(x+1,1,3);
}
return search(x,y+1,3);
}
static boolean search(int x,int y,int size){
if(res==0&&total==0){
return true;
}
else if(total<res*5||total>res*13){
return false;
}
else if(res==0){
return false;
}
if(x==9){
return false;
}
if(x>2&&y==1){
for(int i=0;i<10;i++){
if(map[x-3][i]!=0){
return false;
}
}
}
while(true){
switch(size){
case 3:if(lcd(x,y)){
       ld(x,y);
       drop[x][y][2]++;
       if(searchnext(x,y)){
       return true;
       }
       else{
       if(scd(x,y)&&search(x,y,3)){
       return true;
       }
       lr(x,y);
       drop[x][y][2]--;
       }
       }
       size--;
case 2:if(mcd(x,y)){
       md(x,y);
       drop[x][y][1]++;
       if(searchnext(x,y)){
       return true;
       }
       else{
       if(search(x,y,2)){
       return true;
       }
       mr(x,y);
       drop[x][y][1]--;
       }
       }
       size--;
case 1:if(scd(x,y)){
       sd(x,y);
       drop[x][y][0]++;
       if(searchnext(x,y)){
       return true;
       }
       else{
       if(scd(x,y)&&search(x,y,1)){
       return true;
       }
       sr(x,y);
       drop[x][y][0]--;
       }
       }
       size--;
case 0:return searchnext(x,y);
}
}
}
}