#include const int32_t MAX_H = 500; const int32_t MAX_W = 500; const int32_t INF = 1e9; const double e = 2.718281828; const clock_t beginTime = clock(); std::mt19937 mt(69); struct Pixel { int32_t r, g, b; Pixel() {} Pixel(int32_t _r, int32_t _g, int32_t _b) : r(_r), g(_g), b(_b) {} void read_pixel() { std::cin >> r >> g >> b; } void print_pixel() const { std::cout << r << " " << g << " " << b << '\n'; } static int32_t calc_distance(const Pixel &p1, const Pixel &p2) { return (p1.r - p2.r) * (p1.r - p2.r) + (p1.g - p2.g) * (p1.g - p2.g) + (p1.b - p2.b) * (p1.b - p2.b); } bool operator< (const Pixel &o) const { if(r != o.r) { return r < o.r; } else if(g != o.g) { return g < o.g; } else { return b < o.b; } } friend bool operator== (const Pixel &lhs, const Pixel &rhs) { return (lhs.r == rhs.r && lhs.b == rhs.b && lhs.g == rhs.g); } friend bool operator!= (const Pixel &lhs, const Pixel &rhs) { return (lhs.r != rhs.r || lhs.b != rhs.b || lhs.g != rhs.g); } static bool cmp_r(const Pixel &x, const Pixel &y) { return x.r < y.r; } static bool cmp_g(const Pixel &x, const Pixel &y) { return x.g < y.g; } static bool cmp_b(const Pixel &x, const Pixel &y) { return x.b < y.b; } }; struct Image { int32_t h, w; Pixel pixels[MAX_H + 5][MAX_W + 5]; void read_image() { std::cin >> w >> h; for(int32_t i = 0; i < h; i++) { for(int32_t j = 0; j < w; j++) { pixels[i][j].read_pixel(); } } } void print_image() const { for(int32_t i = 0; i < h; i++) { for(int32_t j = 0; j < w; j++) { pixels[i][j].print_pixel(); } } } }; Image input, output; std::vector< std::vector< int32_t > > res; std::vector< Pixel > pallete; int64_t calculate_distance_pallete() { int64_t d = 0; for(int32_t i = 0; i < input.h; i++) { for(int32_t j = 0; j < input.w; j++) { int32_t minD = INF; for(int32_t p = 0; p < 16; p++) { minD = std::min(minD, Pixel::calc_distance(input.pixels[i][j], pallete[p])); } d += (int64_t) minD; } } return d; } void generate_pallete() { pallete.resize(16, Pixel(0, 0, 0)); std::vector< std::vector< Pixel > > allPixels(16, std::vector< Pixel >()); for(int32_t i = 0; i < input.h; i++) { for(int32_t j = 0; j < input.w; j++) { allPixels[0].push_back(input.pixels[i][j]); } } std::queue< int32_t > q; q.push(0); int32_t ind = 1; while(ind < 16) { int32_t p = q.front(); q.pop(); int32_t minR = INF, maxR = 0, minG = INF, maxG = 0, minB = INF, maxB = 0; for(auto &x : allPixels[p]) { minR = std::min(x.r, minR); maxR = std::max(x.r, maxR); minG = std::min(x.g, minG); maxG = std::max(x.g, maxG); minB = std::min(x.b, minB); maxB = std::max(x.b, maxB); } if(maxR - minR >= maxG - minG && maxR - minR >= maxB - minB) { std::sort(allPixels[p].begin(), allPixels[p].end(), Pixel::cmp_r); } else if(maxG - minG >= maxR - minR && maxG - minG >= maxB - minB) { std::sort(allPixels[p].begin(), allPixels[p].end(), Pixel::cmp_g); } else { std::sort(allPixels[p].begin(), allPixels[p].end(), Pixel::cmp_b); } for(int32_t i = 0; i < allPixels[p].size() / 2; i++) { allPixels[ind].push_back(allPixels[p][i]); } allPixels[p].erase(allPixels[p].begin(), allPixels[p].begin() + allPixels[p].size() / 2); q.push(p); q.push(ind); ind++; } ind = 0; for(auto &p : allPixels) { int32_t r = 0, g = 0, b = 0; for(auto &x : p) { r += x.r; b += x.b; g += x.g; } pallete[ind++] = Pixel(r / p.size(), g / p.size(), b / p.size()); } std::map< Pixel, int32_t > cnt; for(int32_t i = 0; i < input.h; i++) { for(int32_t j = 0; j < input.w; j++) { cnt[input.pixels[i][j]]++; } } std::vector< std::pair< int32_t, Pixel > > aux; for(auto &x : pallete) { aux.push_back({ 0, x }); } for(auto &x : cnt) { aux.push_back({ x.second, x.first }); } if(aux.size() <= 16) { return; } int64_t bestD = calculate_distance_pallete(); for(int32_t i = 0; ; i++) { if(((double) clock() - beginTime) / (double) CLOCKS_PER_SEC > 4.7) { break; } int32_t toRemove = mt() % 16; int32_t toInsert = mt() % (aux.size() - 16) + 16; std::pair< int32_t, Pixel > p = { 0, pallete[toRemove] }; pallete[toRemove] = aux[toInsert].second; aux[toInsert] = p; int64_t currD = calculate_distance_pallete(); if(currD < bestD) { bestD = currD; } else { p = { 0, pallete[toRemove] }; pallete[toRemove] = aux[toInsert].second; aux[toInsert] = p; } } } void compress_image() { input.read_image(); generate_pallete(); res.resize(input.h, std::vector< int32_t >(input.w)); for(int32_t i = 0; i < input.h; i++) { for(int32_t j = 0; j < input.w; j++) { int32_t best = INF, ind; for(int32_t p = 0; p < 16; p++) { auto &c = pallete[p]; int32_t curr = Pixel::calc_distance(c, input.pixels[i][j]); if(curr < best) { best = curr; ind = p; } } res[i][j] = ind; } } } void decompress_image() { std::cin >> output.w >> output.h; for(int32_t i = 0; i < output.h; i++) { for(int32_t j = 0; j < output.w; j++) { int32_t p; std::cin >> p; output.pixels[i][j] = pallete[p]; } } std::vector< std::vector< double > > kernel = { { 0, 0.2, 0 }, { 0.2, 1.1, 0.2 }, { 0, 0.2, 0 } }; for(int32_t i = 1; i < output.h - 1; i++) { for(int32_t j = 1; j < output.w - 1; j++) { double r = 0, g = 0, b = 0, sum = 0; for(int32_t p = -1; p <= 1; p++) { for(int32_t q = -1; q <= 1; q++) { r += output.pixels[i + p][j + q].r * kernel[p + 1][q + 1]; g += output.pixels[i + p][j + q].g * kernel[p + 1][q + 1]; b += output.pixels[i + p][j + q].b * kernel[p + 1][q + 1]; sum += kernel[p + 1][q + 1]; } } output.pixels[i][j] = Pixel((int32_t) (r / sum), (int32_t) (g / sum), (int32_t) (b / sum)); } } } int main() { std::freopen("imrec.in", "r", stdin); std::freopen("imrec.out", "w", stdout); int32_t p; std::cin >> p; if(p == 0) { compress_image(); for(auto &c : pallete) { c.print_pixel(); } for(int32_t i = 0; i < input.h; i++) { for(int32_t j = 0; j < input.w; j++) { std::cout << res[i][j] << " "; } std::cout << '\n'; } return 0; } else { pallete.resize(16); for(int32_t i = 0; i < 16; i++) { pallete[i].read_pixel(); } decompress_image(); output.print_image(); return 0; } }