結果
問題 | No.5002 stick xor |
ユーザー | Hoi_koro |
提出日時 | 2018-05-28 14:55:09 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 958 ms / 1,000 ms |
コード長 | 14,770 bytes |
コンパイル時間 | 35,336 ms |
実行使用メモリ | 1,744 KB |
スコア | 49,669 |
最終ジャッジ日時 | 2018-05-28 14:55:46 |
ジャッジサーバーID (参考情報) |
judge9 / |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 956 ms
1,740 KB |
testcase_01 | AC | 957 ms
1,736 KB |
testcase_02 | AC | 956 ms
1,740 KB |
testcase_03 | AC | 954 ms
1,740 KB |
testcase_04 | AC | 957 ms
1,740 KB |
testcase_05 | AC | 954 ms
1,736 KB |
testcase_06 | AC | 957 ms
1,740 KB |
testcase_07 | AC | 956 ms
1,740 KB |
testcase_08 | AC | 954 ms
1,736 KB |
testcase_09 | AC | 957 ms
1,740 KB |
testcase_10 | AC | 957 ms
1,740 KB |
testcase_11 | AC | 957 ms
1,740 KB |
testcase_12 | AC | 955 ms
1,740 KB |
testcase_13 | AC | 956 ms
1,740 KB |
testcase_14 | AC | 956 ms
1,744 KB |
testcase_15 | AC | 956 ms
1,740 KB |
testcase_16 | AC | 954 ms
1,736 KB |
testcase_17 | AC | 954 ms
1,740 KB |
testcase_18 | AC | 956 ms
1,740 KB |
testcase_19 | AC | 957 ms
1,740 KB |
testcase_20 | AC | 957 ms
1,740 KB |
testcase_21 | AC | 956 ms
1,740 KB |
testcase_22 | AC | 956 ms
1,740 KB |
testcase_23 | AC | 957 ms
1,740 KB |
testcase_24 | AC | 957 ms
1,740 KB |
testcase_25 | AC | 957 ms
1,736 KB |
testcase_26 | AC | 955 ms
1,740 KB |
testcase_27 | AC | 957 ms
1,740 KB |
testcase_28 | AC | 956 ms
1,740 KB |
testcase_29 | AC | 958 ms
1,744 KB |
testcase_30 | AC | 956 ms
1,740 KB |
testcase_31 | AC | 958 ms
1,740 KB |
ソースコード
#include <bits/stdc++.h> // make_tuple emplace_back next_permutation push_back make_pair second first // setprecision #if MYDEBUG #include "lib/cp_debug.hpp" #else #define DBG(...) ; #endif using LL = long long; constexpr LL LINF = 334ll << 53; constexpr int INF = 15 << 26; constexpr LL MOD = 1E9 + 7; namespace Problem { using namespace std; struct Rec { int dir, // direction(0,horizontal, 1:vertical), y, x; // coordinate left-upper corner }; uint32_t x = 123456789, y = 362436069, z = 521288629, w = 88675123; uint32_t xor128() { uint32_t t = x ^ (x << 11); x = y; y = z; z = w; return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); } class Solver { public: int n, k; const int ub = 25; vector<int> len; vector<vector<int>> grid, flip, len_id; vector<Rec> rec, ans; random_device rnd; mt19937 mt; chrono::system_clock::time_point start = chrono::system_clock::now(); Solver(LL n, LL k) : n(n), k(k), len(k), grid(n, vector<int>(n)), len_id(ub + 1), rec(k), mt(rnd()){}; void calc_SA() { double temperature = 10.0; int q, d, x, y; int score = -evaluate(grid, rec), max_score = score; DBG(score) for (int i = 0; i < k; ++i) { d = xor128() % 2; y = xor128() % n; x = xor128() % (n - len[i] + 1); if (d == 1) swap(x, y); add_rectangle(grid, rec, i, d, y, x, true); } score += evaluate(grid, rec); max_score = score; ans = rec; DBG(score) int loop = 0; while (!time_limit()) { for (int _ = 0; _ < 10000; ++_) { loop++; q = xor128() % k; d = xor128() % 2; y = xor128() % n; x = xor128() % (n - len[q] + 1); if (d == 1) swap(x, y); auto tmp = rec[q]; double diff = remove_rectangle(grid, rec, q, true) + add_rectangle(grid, rec, q, d, y, x, true); double diff2 = remove_rectangle(grid, rec, q, true) + add_rectangle(grid, rec, q, tmp.dir, tmp.y, tmp.x, true); if ((double)xor128() / (double)(1ll << 32) < exp(diff / temperature)) { remove_rectangle(grid, rec, q, true) + add_rectangle(grid, rec, q, d, y, x, true); // DBG(score, diff) score += diff; if (score > max_score) { max_score = score; ans = rec; } } } DBG(temperature, score) temperature = update_temp(); } cerr << score << ' ' << max_score << ' ' << loop << endl; } void calc_RESA() { double temp1 = 0.5, temp2 = 2.0, temp3 = 5.0; int q, d, x, y; int score1 = -evaluate(grid, rec), max_score, score2, score3; double diff; DBG(score1) for (int i = 0; i < k; ++i) { d = xor128() % 2; y = xor128() % n; x = xor128() % (n - len[i] + 1); if (d == 1) swap(x, y); add_rectangle(grid, rec, i, d, y, x, true); } vector<Rec> rec1, rec2, rec3; rec1 = rec2 = rec3 = rec; vector<vector<int>> gr1, gr2, gr3; gr1 = gr2 = gr3 = grid; score1 += evaluate(grid, rec); max_score = score2 = score3 = score1; ans = rec; DBG(score1) int loop = 0; while (!time_limit()) { DBG(score1, score2, score3) for (int _ = 0; _ < 10000; ++_) { // first q = xor128() % k; x = xor128() % 2 * 2 - 1; if (rec1[q].dir == 0) { if (x == -1 and rec1[q].x > 0) { diff = (gr1[rec1[q].y][rec1[q].x - 1] + gr1[rec1[q].y][rec1[q].x + len[q] - 1]) * 2 - 2; if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) { gr1[rec1[q].y][rec1[q].x - 1] ^= 1; gr1[rec1[q].y][rec1[q].x + len[q] - 1] ^= 1; rec1[q].x--; score1 += diff; if (score1 > max_score) { max_score = score1; ans = rec1; } } } else if (x == 1 and rec1[q].x + len[q] < n) { diff = (gr1[rec1[q].y][rec1[q].x] + gr1[rec1[q].y][rec1[q].x + len[q]]) * 2 - 2; if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) { gr1[rec1[q].y][rec1[q].x] ^= 1; gr1[rec1[q].y][rec1[q].x + len[q]] ^= 1; rec1[q].x++; score1 += diff; if (score1 > max_score) { max_score = score1; ans = rec1; } } } } else { if (x == -1 and rec1[q].y > 0) { diff = (gr1[rec1[q].y - 1][rec1[q].x] + gr1[rec1[q].y + len[q] - 1][rec1[q].x]) * 2 - 2; if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) { gr1[rec1[q].y - 1][rec1[q].x] ^= 1; gr1[rec1[q].y + len[q] - 1][rec1[q].x] ^= 1; rec1[q].y--; score1 += diff; if (score1 > max_score) { max_score = score1; ans = rec1; } } } else if (x == 1 and rec1[q].y + len[q] < n) { diff = (gr1[rec1[q].y][rec1[q].x] + gr1[rec1[q].y + len[q]][rec1[q].x]) * 2 - 2; if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) { gr1[rec1[q].y][rec1[q].x] ^= 1; gr1[rec1[q].y + len[q]][rec1[q].x] ^= 1; rec1[q].y++; score1 += diff; if (score1 > max_score) { max_score = score1; ans = rec1; } } } } // second : swap the length of two rectangles q = xor128() % k; do { d = xor128() % k; } while (rec2[d].dir != rec2[q].dir or (rec2[d].dir == 0 and rec2[q].y == rec2[d].y) or (rec2[d].dir == 1 and rec2[q].x == rec2[d].x)); if (len[q] < len[d]) swap(q, d); diff = -2 * (len[q] - len[d]); if (len[q] > len[d]) { if (rec2[d].dir == 0 and rec2[d].x + len[q] <= n) { for (int l = len[d]; l < len[q]; ++l) { diff += gr2[rec2[q].y][rec2[q].x + l] * 2; diff += gr2[rec2[d].y][rec2[d].x + l] * 2; } if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp2)) { score2 += diff; for (int l = len[d]; l < len[q]; ++l) { gr2[rec2[q].y][rec2[q].x + l] ^= 1; gr2[rec2[d].y][rec2[d].x + l] ^= 1; } swap(rec2[q], rec2[d]); if (score2 > max_score) { max_score = score2; ans = rec2; } } } else if (rec2[d].dir == 1 and rec2[d].y + len[q] <= n) { for (int l = len[d]; l < len[q]; ++l) { diff += gr2[rec2[q].y + l][rec2[q].x] * 2; diff += gr2[rec2[d].y + l][rec2[d].x] * 2; } if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp2)) { score2 += diff; for (int l = len[d]; l < len[q]; ++l) { gr2[rec2[q].y + l][rec2[q].x] ^= 1; gr2[rec2[d].y + l][rec2[d].x] ^= 1; } swap(rec2[q], rec2[d]); if (score2 > max_score) { max_score = score2; ans = rec2; } } } } // third loop++; q = xor128() % k; d = xor128() % 2; y = xor128() % n; x = xor128() % (n - len[q] + 1); if (d == 1) swap(x, y); auto tmp = rec3[q]; diff = remove_rectangle(gr3, rec3, q, true) + add_rectangle(gr3, rec3, q, d, y, x, true); remove_rectangle(gr3, rec3, q, true); add_rectangle(gr3, rec3, q, tmp.dir, tmp.y, tmp.x, true); if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp3)) { remove_rectangle(gr3, rec3, q, true) + add_rectangle(gr3, rec3, q, d, y, x, true); // DBG(score, diff) score3 += diff; if (score3 > max_score) { max_score = score3; ans = rec3; } } // swap if ((double)xor128() / (double)(1ll << 32) < exp((score2 - score1) * (temp2 - temp1) / (temp1 * temp2))) { swap(rec1, rec2); swap(gr1, gr2); swap(score1, score2); } if ((double)xor128() / (double)(1ll << 32) < exp((score3 - score2) * (temp3 - temp2) / (temp2 * temp3))) { swap(rec2, rec3); swap(gr2, gr3); swap(score2, score3); } } DBG(temp1, score1) temp3 = update_temp(); temp2 = temp3 * 1; temp1 = temp3 * 1; } cerr << max_score << ' ' << loop << endl; } int evaluate(vector<vector<int>> &gr, vector<Rec> &r) { int ret = n * n; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { ret -= gr[i][j]; } } return ret; } int remove_rectangle(vector<vector<int>> &gr, vector<Rec> &r, int i, bool ex = false) { int ret = 0; int yy = r[i].y; int xx = r[i].x; for (int j = 0; j < len[i]; ++j) { ret += (gr[yy][xx]); if (ex) gr[yy][xx] ^= 1; if (r[i].dir == 0) { xx++; } else { yy++; } } return 2 * ret - len[i]; } int add_rectangle(vector<vector<int>> &gr, vector<Rec> &r, int i, int dir, int y, int x, bool ex = false) { if (ex) r[i] = {dir, y, x}; int ret = 0; for (int j = 0; j < len[i]; ++j) { ret += (gr[y][x]); if (ex) gr[y][x] ^= 1; if (dir == 0) { x++; } else { y++; } } return 2 * ret - len[i]; } void input() { for (int i = 0; i < k; ++i) { cin >> len[i]; } for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { char tmp; cin >> tmp; grid[i][j] = tmp - '0'; } } } void output() { for (int i = 0; i < k; ++i) { if (ans[i].dir == 0) { cout << ans[i].y + 1 << ' ' << ans[i].x + 1 << ' ' << ans[i].y + 1 << ' ' << ans[i].x + len[i] << "\n"; } else { cout << ans[i].y + 1 << ' ' << ans[i].x + 1 << ' ' << ans[i].y + len[i] << ' ' << ans[i].x + 1 << "\n"; } } } void solve() { input(); // randomize initial state uniform_int_distribution<int> seed(0, 100); int loop = seed(mt); for (int i = 0; i < loop; ++i) { xor128(); } calc_RESA(); output(); } bool time_limit(double thres = 0.95) { double t = chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now() - start) .count() / 1000.0; #if MYDEBUG thres *= 4.7; #else ; #endif return t > thres; } double update_temp() { double t_left = (1000 - chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now() - start) .count()); #if MYDEBUG t_left = (4700 - chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now() - start) .count()) / 4.7; #else ; #endif return t_left / 1500; } }; // namespace Problem } // namespace Problem int main() { std::cin.tie(0); std::ios_base::sync_with_stdio(false); long long n = 0, k; std::cin >> n >> k; Problem::Solver sol(n, k); sol.solve(); return 0; }