#include #define endl '\n' using namespace std; const int32_t MAX_N = 305; const int32_t MAX_K = 13; class Color { public: int32_t r, g, b; Color(int32_t r = 0, int32_t g = 0, int32_t b = 0) : r(r), g(g), b(b) { } bool operator== (const Color &x) const { if(x.r == r && x.g == g && x.b == b) { return true; } else { return false; } } static Color Combine(const Color &x, const Color &y) { return Color((x.r + y.r) / 2, (x.g + y.g) / 2, (x.b + y.b) / 2); } static int32_t GetDiff(const Color &x, const Color &y) { return (x.r - y.r) * (x.r - y.r) + (x.g - y.g) * (x.g - y.g) + (x.b - y.b) * (x.b - y.b); } }; class Command { public: int32_t type, param1, param2, param3, param4; Command(int32_t type = 0, int32_t param1 = 0, int32_t param2 = 0, int32_t param3 = 0, int32_t param4 = 0) : type(type), param1(param1), param2(param2), param3(param3), param4(param4) { } }; bool isVisited[MAX_N][MAX_N]; int32_t n, k, darkestVal = 1e9 + 7, lightestVal = 0, middleVal, middleInd, darkestInd, lightestInd; Color pallete[MAX_K], target[MAX_N][MAX_N], active, ans[MAX_N][MAX_N]; pair< int32_t, int32_t > colorVals[MAX_K]; int main() { freopen("drawing.in", "r", stdin); freopen("drawing.out", "w", stdout); ios_base::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> k; for(int32_t i = 1; i <= k; i++) { int32_t r, g, b; cin >> r >> g >> b; pallete[i] = Color(r, g, b); colorVals[i] = { r * r + g * g + b * b, i }; } sort(colorVals + 1, colorVals + 1 + k); for(int32_t i = 1; i <= n; i++) { for(int32_t j = 1; j <= n; j++) { cin >> target[i][j].r; } } for(int32_t i = 1; i <= n; i++) { for(int32_t j = 1; j <= n; j++) { cin >> target[i][j].g; } } for(int32_t i = 1; i <= n; i++) { for(int32_t j = 1; j <= n; j++) { cin >> target[i][j].b; } } active = Color(255, 255, 255); vector< Color > possibleColors; vector< int32_t > parColor; possibleColors.push_back(active); parColor.push_back(0); for(int32_t i = k; i >= 1; i--) { while(1) { active = Color::Combine(active, pallete[colorVals[i].second]); if(active == possibleColors[possibleColors.size() - 1]) { break; } possibleColors.push_back(active); parColor.push_back(colorVals[i].second); } } for(int32_t p = 1; p <= 18; p++) { random_shuffle(colorVals + 1, colorVals + 1 + k); for(int32_t i = 1; i <= k; i++) { while(1) { active = Color::Combine(active, pallete[colorVals[i].second]); if(active == possibleColors[possibleColors.size() - 1]) { break; } possibleColors.push_back(active); parColor.push_back(colorVals[i].second); } } } for(int32_t i = 1; i <= n; i++) { for(int32_t j = 1; j <= n; j++) { ans[i][j] = { 255, 255, 255 }; } } for(int32_t i = 1; i <= n; i++) { for(int32_t j = 1; j <= n; j++) { int32_t best = -1; Color bestColor; for(auto c : possibleColors) { int32_t curr = Color::GetDiff(target[i][j], c); if(best == -1 || curr < best) { best = curr; bestColor = c; } } ans[i][j] = bestColor; } } ans[1][1] = Color(255, 255, 255); isVisited[1][1] = true; vector< Command > commands; commands.push_back(Command(1, 0)); int32_t colorInd = 1; while(1) { for(int32_t i = 1; i <= n; i++) { for(int32_t j = 1; j <= n; j++) { if(isVisited[i][j] || !(ans[i][j] == possibleColors[colorInd])) { continue; } vector< int32_t > rows; for(int32_t i1 = i; i1 <= n; i1++) { if(isVisited[i1][j] || !(ans[i1][j] == ans[i][j])) { break; } int32_t cnt = 0; for(int32_t j1 = j; j1 <= n; j1++) { if(isVisited[i1][j1] || !(ans[i1][j1] == ans[i][j])) { break; } cnt++; } rows.push_back(cnt); } int32_t currMin = n + 1, maxArea = 0, w, h = 1; for(int32_t i1 = i; i1 <= n; i1++) { if(isVisited[i1][j] || !(ans[i1][j] == ans[i][j])) { break; } if(currMin > rows[i1 - i]) { currMin = rows[i1 - i]; } if(currMin * (i1 - i + 1) <= 200 && currMin * (i1 - i + 1) > maxArea) { maxArea = currMin * (i1 - i + 1); w = currMin; h = i1 - i + 1; } } for(int32_t i1 = 0; i1 < h; i1++) { for(int32_t j1 = 0; j1 < w; j1++) { isVisited[i + i1][j + j1] = true; } } commands.push_back(Command(3, i, j, i + h - 1, j + w - 1)); } } colorInd++; if(colorInd == possibleColors.size()) { break; } commands.push_back(Command(1, parColor[colorInd] - 1)); } while(commands.size() < 90000) { for(int32_t i = 1; i <= n; i++) { for(int32_t j = 1; j <= n; j++) { if(i == 1 && j == 1) { continue; } Color c = ans[i][j]; c = Color::Combine(c, active); int32_t currDiff = Color::GetDiff(ans[i][j], target[i][j]); int32_t diff1 = Color::GetDiff(c, target[i][j]); int32_t diff2 = Color::GetDiff(active, target[i][j]); if(diff1 <= diff2 && diff1 < currDiff) { ans[i][j] = c; commands.push_back(Command(4, i, j, i, j)); } else if(diff2 <= diff1 && diff2 < currDiff) { ans[i][j] = active; commands.push_back(Command(3, i, j, i, j)); } } } Color lastActive = active; active = Color::Combine(active, ans[1][1]); if(lastActive == active) { break; } commands.push_back(Command(2, 1, 1)); } for(int32_t i = commands.size() - 1; i >= 0 ; i--) { if(commands[i].type == 1) { commands.pop_back(); } else { break; } } while(commands.size() > 90000) { commands.pop_back(); } cout << commands.size() << endl; for(auto c : commands) { cout << c.type << " "; if(c.type == 1) { cout << c.param1 << endl; } else if(c.type == 2) { cout << c.param1 - 1 << " " << c.param2 - 1 << endl; } else { cout << c.param1 - 1 << " " << c.param2 - 1 << " " << c.param3 - 1 << " " << c.param4 - 1 << endl; } } return 0; }