1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <iostream>
#include <unordered_map>
#include <vector>
#include <stack>
#include <utility>

namespace {
	using std::ios_base, std::cin, std::cout;
	using std::swap, std::get;

	using multi_t = std::unordered_map<char, size_t>;
	using v_multi_t = std::vector<multi_t>;
	using moves_t = std::stack<std::tuple<char, size_t, char>>;

	void next_turn(char active_symbol, v_multi_t & active, 
	               v_multi_t & passive, moves_t & moves) {
		char color;
		for (size_t k = 0; k < active.size(); ++k) {
			if (active[k].size() == 1) {
				color = active[k].begin()->first;
				active[k].erase(active[k].begin());
				for (auto & elt : passive) {
					auto it = elt.find(color);
					if (it != elt.end() && it->second > 0) {
						--it->second;
						if (it->second == 0)
							elt.erase(it);
					}
				}
				moves.push({active_symbol, k + 1, color});
			}
		}
	}
};

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	// Wczytanie danych
	size_t n, m;
	char color;
	cin >> n;
	cin >> m;
	v_multi_t in_rows(n), in_cols(m);
	for (size_t row = 0; row < n; ++row) {
		for (size_t col = 0; col < m; ++col) {
			cin >> color;
			if (!in_rows[row].insert({color, 1}).second)
				++in_rows[row][color];
			if (!in_cols[col].insert({color, 1}).second)
				++in_cols[col][color];
		}
	}

	// Obliczenie wyniku
	moves_t moves;
	bool end = false, no_colors;
	char symbol = 'R';
	size_t id;
	do {
		next_turn(symbol, in_rows, in_cols, moves);
		id = 0;
		no_colors = true;
		while (no_colors && id < in_rows.size()) {
			if (in_rows[id].size() != 0)
				no_colors = false;
			++id;
		}
		if (no_colors) {
			end = true;
		} else {
			swap(in_rows, in_cols);
			if (symbol == 'R')
				symbol = 'K';
			else
				symbol = 'R';
		}
	
	} while (!end);

	// Drukowanie wyniku
	cout << moves.size() << '\n';
	while (!moves.empty()) {
		auto top_move = moves.top();
		cout << get<0>(top_move) << ' ' << get<1>(top_move) << ' ' 
		     << get<2>(top_move) << '\n';
		moves.pop();
	}
}