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: Time Limit Exceeded)



import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;



 class Main{
     
    static int kami[][]=new int[10][10];
    static int maxDrop=0;
    static ArrayList<drop> answer = new ArrayList<drop>();
    class drop{
        int x , y , size;
        drop(int x,int y,int size){this.x=x;this.y=y;this.size=size;}
        void doDro(){
            switch(size){
                case 3:kami[x-2][y]--;kami[x+2][y]--;kami[x][y-2]--;kami[x][y+2]--;
                case 2:kami[x-1][y-1]--;kami[x-1][y+1]--;kami[x+1][y-1]--;kami[x+1][y+1]--;
                case 1:kami[x][y]--;kami[x-1][y]--;kami[x+1][y]--;kami[x][y+1]--;kami[x][y-1]--; break;} 
        }
        void undoDro(){
            switch(size){
                case 3:kami[x-2][y]++;kami[x+2][y]++;kami[x][y-2]++;kami[x][y+2]++;
                case 2:kami[x-1][y-1]++;kami[x-1][y+1]++;kami[x+1][y-1]++;kami[x+1][y+1]++;
                case 1:kami[x][y]++;kami[x-1][y]++;kami[x+1][y]++;kami[x][y+1]++;kami[x][y-1]++; break;} 
        }
        void printDro(){
            System.out.println(y+" "+x+" "+size);
        }
        
    }
    
     public static void main(String args[]){
         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
         try{
             String line;
             line=br.readLine();maxDrop=Integer.parseInt(line);
             //while((line=br.readLine())!=null){if(line.isEmpty())break;
             //}
             for(int i=0; i<10;i++){String spl[] = br.readLine().split(" ");
             for(int j=0;j<10;j++)kami[i][j]=Integer.parseInt(spl[j]);}
             br.close();
             //search Start
             Main m= new Main();
             m.canSearch(0);
             for(drop d:answer){d.printDro();}
             
         }catch(Exception e){}         
     }
     
     boolean canSearch(int now){
         if(now==maxDrop)return isClear();now++;
        
         for(int i=1; i<9;i++){
             for(int j=1; j<9;j++){
                 boolean canLDflag=false,canMDflag=false;
                 if(i!=1&&i!=8&&j!=1&&j!=8){                     
                     if(canLD(i,j)){canLDflag=true;
                         drop d = new drop(i,j,3);
                         d.doDro();if(canSearch(now)){answer.add(d);return true;}
                         else{d.undoDro();}
                     }
                 }
                 if(canLDflag){canMDflag=true;drop d=new drop(i,j,2);d.doDro();
                    if(canSearch(now)){answer.add(d);return true;}
                    else{d.undoDro();}}
                 else if((canMD(i,j))){canMDflag=true;drop d=new drop(i,j,2);d.doDro();
                    if(canSearch(now)){answer.add(d);return true;}
                    else{d.undoDro();}}
                 if(canMDflag==true){drop d=new drop(i,j,1);d.doDro();
                    if(canSearch(now)){answer.add(d);return true;}
                    else{d.undoDro();}}
                 else if(canSD(i,j)){drop d=new drop(i,j,1);d.doDro();
                    if(canSearch(now)){answer.add(d);return true;}
                    else{d.undoDro();}}
                 
             }
         }
         return false;
     }
     static boolean isClear(){for(int i=0;i<=9;i++)for(int j=0;j<=9;j++)if(kami[i][j]!=0)return false;
     return true;}
     static boolean canSD(int x,int y){
         if(x==0||x==9||y==0||y==9)return false;
         return (kami[x-1][y]>0&&kami[x+1][y]>0&&kami[x][y-1]>0&&kami[x][y+1]>0&&kami[x][y]>0);
     }
     static boolean canMD(int x,int y){
         if(x==0||x==9||y==0||y==9)return false;
         return (kami[x-1][y]>0&&kami[x+1][y]>0&&kami[x][y-1]>0&&kami[x][y+1]>0&&kami[x][y]>0&&
                 kami[x-1][y-1]>0&&kami[x-1][y+1]>0&&kami[x+1][y-1]>0&&kami[x+1][y+1]>0);
     }
     static boolean canLD(int x,int y){
         if(x<=1||x>=8||y<=1||y>=8)return false;
         return (kami[x-1][y]>0&&kami[x+1][y]>0&&kami[x][y-1]>0&&kami[x][y+1]>0&&kami[x][y]>0&&
                 kami[x-1][y-1]>0&&kami[x-1][y+1]>0&&kami[x+1][y-1]>0&&kami[x+1][y+1]>0&&
                 kami[x-2][y]>0&&kami[x+2][y]>0&&kami[x][y-2]>0&&kami[x][y+2]>0);
     }
     
 }