// Painter.cpp : Defines the entry point for the console application. // #include #include #include #include #define IMGSIZE_MAX 300 using namespace std; struct Command { char type; int a, b, c, d; }; struct Color { int r, g, b; Color() : r(255), g(255), b(255) {} Color(int r, int g, int b) : r(r), g(g), b(b) {} }; int color_distance(const Color &c1, const Color &c2) { int dr = c1.r - c2.r; int dg = c1.g - c2.g; int db = c1.b - c2.b; return dr * dr + dg * dg + db * db; } int color_maxdiff(const Color &c1, const Color &c2) { int dr = abs(c1.r - c2.r); int dg = abs(c1.g - c2.g); int db = abs(c1.b - c2.b); int drdb = dr > db ? dr : db; return drdb > dg ? drdb : dg; } bool operator==(const Color &lhs, const Color &rhs) { return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b; } class Rectangle { public: int x1, y1, x2, y2; Color color; Rectangle() {} Rectangle(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) {} }; struct by_color { bool operator()(Rectangle const &a, Rectangle const &b) const { return 256 * 256 * a.color.r + 256 * a.color.g + a.color.b >= 256 * 256 * b.color.r + 256 * b.color.g + b.color.b; } }; Color mix_colors(Color col1, Color col2) { return Color((col1.r + col2.r) / 2, (col1.g + col2.g) / 2, (col1.b + col2.b) / 2); } struct by_color_distance { Color active, target; by_color_distance(Color active, Color target) : active(active), target(target) {} bool operator()(pair const &a, pair const &b) { return color_distance(target, mix_colors(active, a.second)) < color_distance(target, mix_colors(active, b.second)); } }; void paint_replace(Color canvas[IMGSIZE_MAX][IMGSIZE_MAX], Color col, Rectangle rect) { for (int y = rect.y1; y <= rect.y2; ++y) { for (int x = rect.x1; x <= rect.x2; ++x) { canvas[y][x] = col; } } } void paint_average(Color canvas[IMGSIZE_MAX][IMGSIZE_MAX], Color col, Rectangle rect) { for (int y = rect.y1; y <= rect.y2; ++y) { for (int x = rect.x1; x <= rect.x2; ++x) { canvas[y][x] = mix_colors(canvas[y][x], col); } } } Color get_average(Color target[IMGSIZE_MAX][IMGSIZE_MAX], Rectangle rect) { Color avg = Color(0, 0, 0); int n = 0; for (int y = rect.y1; y <= rect.y2; ++y) { for (int x = rect.x1; x <= rect.x2; ++x) { avg.r += target[y][x].r; avg.g += target[y][x].g; avg.b += target[y][x].b; n += 1; } } avg.r /= n; avg.g /= n; avg.b /= n; return avg; } int min_distance(Color active, Color target, vector> palette) { int min_pos = distance(palette.begin(), min_element(palette.begin(), palette.end(), by_color_distance(active, target))); return (color_distance(active, target) > color_distance(target, mix_colors(active, palette[min_pos].second))) ? min_pos : -1; } bool should_add_color_to_palette(Color col, vector> palette) { for (auto pcol : palette) { if (color_maxdiff(pcol.second, col) < 10) { return false; } } return true; } int N, K; Color target[IMGSIZE_MAX][IMGSIZE_MAX]; int main() { freopen("drawing.in", "r", stdin); freopen("drawing.out", "w", stdout); vector> palette; scanf("%d %d", &N, &K); for (int i = 0; i < K; ++i) { Color col; scanf("%d %d %d", &col.r, &col.g, &col.b); palette.push_back(pair(-1, col)); } for (int k = 0; k < 3; ++k) { for (int j = 0; j < N; ++j) { for (int i = 0; i < N; ++i) { scanf("%d", &(&target[i][j].r)[k]); } } } Color active; // default is white int w = 2; int h = 2; vector rects; for (int i = 0; i < N / h; ++i) { for (int j = 0; j < N / w; ++j) { Rectangle rect(j * w, i * h, j * w + w - 1, i * h + h - 1); rect.color = get_average(target, rect); rects.push_back(rect); } } random_shuffle(rects.begin(), rects.end()); sort(rects.begin() + 200, rects.end(), by_color()); vector commands; int n = 0; for (auto rect : rects) { int min_id; int lim = 0; while ((min_id = min_distance(active, rect.color, palette)) != -1 && ((lim++ < 10 && palette.size() < 100) || lim < 4)) { Command com; if (palette[min_id].first == -1) { com.type = 1; com.a = min_id; } else { com.type = 2; com.a = palette[min_id].first % N; com.b = palette[min_id].first / N; } commands.push_back(com); n++; active = mix_colors(active, palette[min_id].second); } Command com; com.type = 3; com.a = rect.x1; com.b = rect.y1; com.c = rect.x2; com.d = rect.y2; commands.push_back(com); n++; if (should_add_color_to_palette(active, palette)) { palette.push_back(pair((rect.x1 + rect.x2) / 2 + (rect.y1 + rect.y2) / 2 * N, active)); } } printf("%d\n", n); for (auto com : commands) { switch (com.type) { case 1: printf("1 %d\n", com.a); break; case 2: printf("2 %d %d\n", com.a, com.b); break; default: printf("%d %d %d %d %d\n", com.type, com.a, com.b, com.c, com.d); } } printf("%d\n", palette.size()); return 0; }