結果
問題 | No.5002 stick xor |
ユーザー | Hoi_koro |
提出日時 | 2018-05-28 22:35:47 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 978 ms / 1,000 ms |
コード長 | 15,963 bytes |
コンパイル時間 | 35,816 ms |
実行使用メモリ | 1,780 KB |
スコア | 49,803 |
最終ジャッジ日時 | 2018-05-28 22:36:25 |
ジャッジサーバーID (参考情報) |
judge9 / |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 978 ms
1,732 KB |
testcase_01 | AC | 976 ms
1,732 KB |
testcase_02 | AC | 976 ms
1,780 KB |
testcase_03 | AC | 974 ms
1,736 KB |
testcase_04 | AC | 977 ms
1,772 KB |
testcase_05 | AC | 975 ms
1,732 KB |
testcase_06 | AC | 976 ms
1,732 KB |
testcase_07 | AC | 976 ms
1,732 KB |
testcase_08 | AC | 975 ms
1,772 KB |
testcase_09 | AC | 976 ms
1,728 KB |
testcase_10 | AC | 976 ms
1,728 KB |
testcase_11 | AC | 975 ms
1,728 KB |
testcase_12 | AC | 976 ms
1,728 KB |
testcase_13 | AC | 976 ms
1,728 KB |
testcase_14 | AC | 975 ms
1,728 KB |
testcase_15 | AC | 976 ms
1,732 KB |
testcase_16 | AC | 974 ms
1,732 KB |
testcase_17 | AC | 976 ms
1,732 KB |
testcase_18 | AC | 976 ms
1,772 KB |
testcase_19 | AC | 977 ms
1,732 KB |
testcase_20 | AC | 976 ms
1,772 KB |
testcase_21 | AC | 976 ms
1,724 KB |
testcase_22 | AC | 977 ms
1,728 KB |
testcase_23 | AC | 977 ms
1,724 KB |
testcase_24 | AC | 976 ms
1,776 KB |
testcase_25 | AC | 977 ms
1,728 KB |
testcase_26 | AC | 977 ms
1,728 KB |
testcase_27 | AC | 975 ms
1,728 KB |
testcase_28 | AC | 975 ms
1,724 KB |
testcase_29 | AC | 976 ms
1,728 KB |
testcase_30 | AC | 977 ms
1,728 KB |
testcase_31 | AC | 975 ms
1,736 KB |
ソースコード
#include <bits/stdc++.h> #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<LL> grid; 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, 0), 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); } 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) + add_rectangle(grid, rec, q, d, y, x); remove_rectangle(grid, rec, q); add_rectangle(grid, rec, q, tmp.dir, tmp.y, tmp.x); if ((double)xor128() / (double)(1ll << 32) < exp(diff / temperature)) { remove_rectangle(grid, rec, q); add_rectangle(grid, rec, q, d, y, x); // DBG(score, diff) score += diff; if (score > max_score) { max_score = score; ans = rec; } } } DBG(temperature, score) temperature = update_temperature(); } cerr << score << ' ' << max_score << ' ' << loop << endl; } void calc_RESA() { double temp1 = 0.98, temp2 = 0.99, temp3 = 1.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); } vector<Rec> rec1, rec2, rec3; rec1 = rec2 = rec3 = rec; vector<LL> 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()) { // cerr << temp3 << ' ' << score1 << ' ' << score2 << ' ' << score3 // << endl; 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)) & 1) + ((gr1[rec1[q].y] >> (rec1[q].x + len[q] - 1)) & 1)) * 2 - 2; if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) { gr1[rec1[q].y] ^= (1ll << (rec1[q].x - 1)); gr1[rec1[q].y] ^= (1ll << (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].x + len[q] < n) { 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] ^= (1ll << (rec1[q].x)); gr1[rec1[q].y] ^= (1ll << (rec1[q].x + len[q])); 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)) & 1) + ((gr1[rec1[q].y + len[q] - 1] >> (rec1[q].x)) & 1)) * 2 - 2; if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) { gr1[rec1[q].y - 1] ^= (1ll << rec1[q].x); gr1[rec1[q].y + len[q] - 1] ^= (1ll << rec1[q].x); 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)) & 1) + ((gr1[rec1[q].y + len[q]] >> (rec1[q].x)) & 1)) * 2 - 2; if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp1)) { gr1[rec1[q].y] ^= (1ll << rec1[q].x); gr1[rec1[q].y + len[q]] ^= (1ll << rec1[q].x); 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) { LL mask = (1ll << len[q]) - (1ll << len[d]); diff += __builtin_popcountll((mask << rec2[q].x) & gr2[rec2[q].y]) * 2; diff += __builtin_popcountll((mask << rec2[d].x) & gr2[rec2[d].y]) * 2; /*for (int l = len[d]; l < len[q]; ++l) { diff += ((gr2[rec2[q].y] >> (rec2[q].x + l)) & 1) << 1; diff += ((gr2[rec2[d].y] >> (rec2[d].x + l)) & 1) << 1; }*/ if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp2)) { score2 += diff; gr2[rec2[q].y] ^= (mask << rec2[q].x); gr2[rec2[d].y] ^= (mask << rec2[d].x); /*for (int l = len[d]; l < len[q]; ++l) { gr2[rec2[q].y] ^= (1ll << (rec2[q].x + l)); gr2[rec2[d].y] ^= (1ll << (rec2[d].x + l)); }*/ 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)) & 1) << 1; diff += ((gr2[rec2[d].y + l] >> (rec2[d].x)) & 1) << 1; } 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] ^= (1ll << rec2[q].x); gr2[rec2[d].y + l] ^= (1ll << rec2[d].x); } 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) + add_rectangle(gr3, rec3, q, d, y, x); if ((double)xor128() / (double)(1ll << 32) < exp(diff / temp3)) { // DBG(score, diff) score3 += diff; if (score3 > max_score) { max_score = score3; ans = rec3; } } else { remove_rectangle(gr3, rec3, q); add_rectangle(gr3, rec3, q, tmp.dir, tmp.y, tmp.x); } // 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_temperature(); temp2 = temp3 * 0.999; temp1 = temp3 * 0.998; // temp2 = temp3 - pow(temp3, 2.01); // temp1 = temp2 - pow(temp2, 2.02); } cerr << max_score << endl; // cerr << loop << endl; } int evaluate(vector<LL> &gr, vector<Rec> &r) { int ret = n * n; for (int i = 0; i < n; ++i) { ret -= __builtin_popcountll(gr[i]); } return ret; } int remove_rectangle(vector<LL> &gr, vector<Rec> &r, int i) { int ret = 0; int yy = r[i].y; int xx = r[i].x; if (r[i].dir == 1) { for (int j = 0; j < len[i]; ++j) { ret += ((gr[yy] >> xx) & 1); gr[yy] ^= (1ll << xx); yy++; } } else { LL mask = (1ll << (xx + len[i])) - (1ll << xx); ret += __builtin_popcountll(mask & gr[yy]); gr[yy] ^= mask; } return 2 * ret - len[i]; } int add_rectangle(vector<LL> &gr, vector<Rec> &r, int i, int dir, int y, int x) { r[i] = {dir, y, x}; int ret = 0; if (dir == 1) { for (int j = 0; j < len[i]; ++j) { ret += ((gr[y] >> x) & 1); gr[y] ^= (1ll << x); y++; } } else { LL mask = (1ll << (x + len[i])) - (1ll << x); ret += __builtin_popcountll(mask & gr[y]); gr[y] ^= mask; } return 2 * ret - len[i]; } void input() { for (int i = 0; i < k; ++i) { cin >> len[i]; } int tmp = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { char tmp; cin >> tmp; grid[i] += ((LL)(tmp - '0') << j); } tmp += __builtin_popcountll(grid[i]); } DBG(tmp) } 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.97) { double t = chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now() - start) .count() / 1000.0; #if MYDEBUG thres *= 2.4; #else ; #endif return t > thres; } double update_temperature() { double t_left = (1000 - chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now() - start) .count()); #if MYDEBUG t_left = (2400 - chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now() - start) .count()) / 2.4; #else ; #endif t_left /= 1000; return 0.8 * pow(t_left, 0.8) * exp((t_left - 1) * 1); // return t_left/2+0.02; } }; // 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; }