1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <queue>
6 #include <utility>
7 #include <bitset>
8 #define FF(i, n) for(int i = 0; i < n; i++)
9 #define FOR(i, a, n) for(int i = a; i < n; i++)
10 #define viewPP(a,n,m) {puts("---");FF(i,n){FF(j,m) cout<<a[i][j] <<' ';puts("");}}
11 //一维作为试用版
12 #define viewP(a, n) {FF(i, n) {cout<<a[i]<<" ";} puts("");}
13 using namespace std;
14
15 const int MAXN = 5;
16 const int hinf = 0x3f3f3f3f;
17 const int COR = 20;
18
19 typedef struct _map {
20 int d[MAXN][MAXN];
21 }M;
22 int r, c, deapth, sol;
23
24 //颜色0~19
25 bool judge_bfs(int x, int y) {
26 if(x >= 0 && x < r && y >= 0 && y < c)
27 return true;
28 return false;
29 }
30
31 int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
32
33 //pcol为原来的col
34 void floorFill(M &gra, int x, int y, int c, int pcol) {
35 gra.d[x][y] = c;
36 int nx, ny;
37 FF(i, 4) {
38 nx = x + dir[i][0], ny = y + dir[i][1];
39 if(judge_bfs(nx, ny) && gra.d[nx][ny] == pcol) {
40 floorFill(gra, nx, ny, c, pcol);
41 }
42 }
43 }
44
45 bool is_zero(const M &gra) {
46 FF(i, r)
47 FF(j, c) {
48 if(gra.d[i][j])
49 return false;
50 }
51 return true;
52 }
53
54 int get_col(M gra) {
55 int tmp[COR] = {0}, cnt = 0;
56 FF(i, r)
57 FF(j, c) {
58 if(!tmp[gra.d[i][j]] && gra.d[i][j] != 0) {
59 tmp[gra.d[i][j]] = 1;
60 cnt++;
61 }
62 }
63 return cnt;
64 }
65
66 struct _path {
67 int x, y, col;
68 }path[1005];
69
70 //相邻颜色
71 void has_col(const M &gra, int x, int y, bool has[]) {
72 FF(i, COR) has[i]=false;
73 int nx, ny;
74 FF(k, 4) {
75 nx = x + dir[k][0];
76 ny = y + dir[k][1];
77 if(judge_bfs(nx, ny) && !has[gra.d[nx][ny]])
78 has[gra.d[nx][ny]] = true;
79 }
80 return ;
81 }
82
83 bitset<1000024> bvst[25];
84 int my_zip(const M &gra) {
85 unsigned __int64 z = 0;
86 FF(i, r)
87 FF(j, c) {
88 z = gra.d[i][j] + z * 131;
89 }
90 return (int)(z % 1000007);
91 }
92
93 void dfs(M gra, int step) {
94 if(step > deapth)
95 return ;
96 //viewPP(gra.d, r, c);
97
98 if(is_zero(gra)) {
99 sol = step;
100 printf("%d\n", sol);
101 FOR(i, 1, step+1)
102 printf("%d %d %d\n", path[i].x, path[i].y, path[i].col);
103 return ;
104 }
105
106 int recol = get_col(gra);
107 if(step + recol > deapth)
108 return ;
109
110 FF(i, r) {
111 FF(j, c) {
112 FF(k, COR) {
113 if(sol != -hinf) return ;
114
115 if(k == gra.d[i][j]) continue;
116 bool color[COR];
117 has_col(gra, i, j, color);//color标志其邻居的颜色
118 if(!color[k] && k != 0) continue;//变为相邻颜色,或者0
119
120 M tmp = gra;
121 //用广搜
122 //3732 Accepted 3768K 4219MS G++ 3709B
123 //update(tmp, i, j, k);
124 //用深搜
125 //3732 Accepted 3736K 250MS G++ 3639B
126 floorFill(tmp, i, j, k, gra.d[i][j]);
127 int t = my_zip(tmp);
128 if(bvst[step+1][t]) continue;
129 bvst[step+1][t] = true;
130
131 path[step+1].x = i+1;
132 path[step+1].y = j+1;
133 path[step+1].col = k;
134 dfs(tmp, step+1);
135 }
136 }
137 }
138 }
139
140 void solve() {
141 sol = -hinf;
142 M gra;
143 FF(i, r)
144 FF(j, c)
145 scanf("%d", &gra.d[i][j]);
146 for(deapth = 1; ; deapth++) {
147 FF(i, deapth+1) bvst[i].reset();
148 dfs(gra, 0);
149 if(sol != -hinf) break;
150 }
151 }
152
153 int main(void) {
154 #ifndef ONLINE_JUDGE
155 freopen("in.txt", "r", stdin);
156 #endif
157 while(scanf("%d %d", &r, &c) == 2) {
158 solve();
159 }
160 return 0;
161 }