結果
問題 | No.5002 stick xor |
ユーザー | hakomo |
提出日時 | 2018-05-29 19:15:07 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 14,041 bytes |
コンパイル時間 | 34,825 ms |
実行使用メモリ | 1,820 KB |
スコア | 0 |
最終ジャッジ日時 | 2018-05-29 19:15:43 |
ジャッジサーバーID (参考情報) |
judge6 / |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | WA | - |
testcase_01 | WA | - |
testcase_02 | WA | - |
testcase_03 | WA | - |
testcase_04 | WA | - |
testcase_05 | WA | - |
testcase_06 | WA | - |
testcase_07 | WA | - |
testcase_08 | WA | - |
testcase_09 | WA | - |
testcase_10 | WA | - |
testcase_11 | WA | - |
testcase_12 | WA | - |
testcase_13 | WA | - |
testcase_14 | WA | - |
testcase_15 | WA | - |
testcase_16 | WA | - |
testcase_17 | WA | - |
testcase_18 | WA | - |
testcase_19 | WA | - |
testcase_20 | WA | - |
testcase_21 | WA | - |
testcase_22 | WA | - |
testcase_23 | WA | - |
testcase_24 | WA | - |
testcase_25 | WA | - |
testcase_26 | WA | - |
testcase_27 | WA | - |
testcase_28 | WA | - |
testcase_29 | WA | - |
testcase_30 | WA | - |
testcase_31 | WA | - |
ソースコード
#include <algorithm> #include <array> #include <chrono> #include <cmath> #include <iostream> #include <random> #include <vector> using namespace std; #define U(v) cerr << #v << ": " << (v) << endl constexpr int dx[] = { 1, 0, -1, 0 }; constexpr int dy[] = { 0, 1, 0, -1 }; class timer { vector<timer> timers; int n = 0; public: double limit = 0.98; double t = 0; timer() {} timer(int size) : timers(size) {} bool elapses() const { return time() - t > limit; } void measure() { t = time() - t; ++n; } void measure(char id) { timers[id].measure(); } void print() { if (n % 2) measure(); for (int i = 0; i < 128; ++i) { if (timers[i].n) cerr << (char)i << ' ' << timers[i].t << 's' << endl; } cerr << " " << t << 's' << endl; } static double time() { #ifdef LOCAL return __rdtsc() / 3.3e9; #else return chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count() / 1000.0; #endif } } timer(128); class { //unsigned y = 2463534242; unsigned y = random_device()(); public: unsigned next() { return y ^= (y ^= (y ^= y << 13) >> 17) << 5; } int next(int b) { return next() % b; } int next(int a, int b) { return next(b - a) + a; } double nextDouble(double b = 1) { return b * next() / 4294967296.0; } double nextDouble(double a, double b) { return nextDouble(b - a) + a; } int operator() (int b) { return next(b); } } rando; struct Rectangle { bool vertical; int x, y, length, id; Rectangle() {} Rectangle(bool vertical, int x, int y, int length, int id) : vertical(vertical), x(x), y(y), length(length), id(id) {} }; struct Line { bool vertical; int y; long long line; Line() {} Line(bool vertical, int y) : vertical(vertical), y(y) {} }; constexpr int N = 60; constexpr int K = 500; int L[K]; bool A[N][N]; long long board[2][N]; vector<int> lineToIndicies[2][N]; vector<Rectangle> states, bestStates; int score, bestScore; inline void flip(const Rectangle& r) { board[r.vertical][r.y] ^= ((1ll << r.length) - 1) << r.x; long long mask = 1ll << r.y; for (int x = r.x; x < r.x + r.length; ++x) board[!r.vertical][x] ^= mask; } inline void flip2(const Rectangle& r, unsigned i) { board[r.vertical][r.y] ^= ((1ll << r.length) - 1) << r.x; if (i - r.x < (unsigned)r.length) board[!r.vertical][i] ^= 1ll << r.y; } int main(int argc, char** argv) { timer.measure(); { int k; cin >> k >> k; for (int i = 0; i < K; ++i) cin >> L[i]; char s[N + 1]; for (int y = 0; y < N; ++y) { cin >> s; for (int x = 0; x < N; ++x) A[y][x] = s[x] == '1'; } } for (int y = 0; y < N; ++y) { for (int x = 0; x < N; ++x) { if (A[y][x]) { board[0][y] |= 1ll << x; board[1][x] |= 1ll << y; } else { --score; } } } vector<int> a1, a2; { pair<int, int> a[K]; for (int i = 0; i < K; ++i) a[i] = { L[i], i }; sort(rbegin(a), rend(a)); for (auto& p : a) { if (p.first > 2) { long long b = -1 << 30; array<int, 3> n; for (int i = 0; i < 2; ++i) { for (int y = 0; y < N; ++y) { for (int x = 0; x < N - p.first + 1; ++x) { long long s = __builtin_popcountll(board[i][y] & ((1ll << p.first) - 1) << x); if (b < s) { b = s; n = { i, x, y }; } } } } lineToIndicies[n[0]][n[2]].emplace_back((int)states.size()); states.emplace_back(!!n[0], n[1], n[2], p.first, p.second); flip(states.back()); } else { (p.first == 1 ? a1 : a2).emplace_back(p.second); score += p.first; } } } for (int y = 0; y < N; ++y) score += N - (int)__builtin_popcountll(board[0][y]); vector<array<Line, 2>> ne; int ni = -1; for (int i = 1; i < N * 2; ++i) { for (int j = 0; j < i; ++j) { ne.emplace_back(array<Line, 2>{ Line{ !!(i & 1), i >> 1 }, { !!(j & 1), j >> 1 } }); if (ne.back()[0].vertical) swap(ne.back()[0], ne.back()[1]); } } random_shuffle(ne.begin(), ne.end(), rando); double heat = 0; for (int iter = -1; ; ) { if ((++iter & 0x7ff) == 0) { double p = 1 - (timer.time() - timer.t) / timer.limit; if (p < 0) break; constexpr double InitialHeat = 0.6; constexpr double FinalHeat = 1e-9; heat = 1 / (p * (InitialHeat - FinalHeat) + FinalHeat); } if (++ni == ne.size()) ni = 0; auto& lines = ne[ni]; bool parallel = lines[0].vertical == lines[1].vertical; static vector<int> indicies; static vector<Rectangle> rectangles; indicies.clear(); rectangles.clear(); lines[0].line = board[lines[0].vertical][lines[0].y]; lines[1].line = board[lines[1].vertical][lines[1].y]; int s0, s1; { auto& p = lineToIndicies[lines[0].vertical][lines[0].y]; auto& q = lineToIndicies[lines[1].vertical][lines[1].y]; s0 = (int)p.size(); s1 = (int)q.size(); for (int n = min(3, s0 + s1); n--; ) { int i = rando.next(s0 + s1); if (i < s0) { indicies.emplace_back(p[i]); flip2(states[p[i]], parallel ? -1 : lines[1].y); swap(p[i], p[--s0]); } else { i -= (int)s0; indicies.emplace_back(q[i]); flip2(states[q[i]], parallel ? -1 : lines[0].y); swap(q[i], q[--s1]); } } } for (int i : indicies) { auto& r = states[i]; long long bn = -1 << 30; rectangles.emplace_back(r); auto& br = rectangles.back(); for (auto& l : lines) { long long line = board[l.vertical][l.y]; long long mask = (1ll << r.length) - 1; for (int x = r.length; x <= N; x += 2) { long long n = __builtin_ctzll(line); x += (int)n; line >>= n; n = __builtin_popcountll(line & mask); if (bn < n) { bn = n; br.vertical = l.vertical; br.y = l.y; br.x = min(N, x) - r.length; if (bn == r.length) break; } line >>= 2; } if (bn == r.length) break; } flip2(br, parallel ? -1 : lines[!br.vertical].y); } for (int last = -1; ; ) { bool updated = false; for (auto& r : rectangles) { long long bn = board[r.vertical][r.y] & ((1ll << r.length) - 1) << r.x; if (bn == 0) if (last == r.id) break; else continue; long long cn = bn = r.length - __builtin_popcountll(bn); flip2(r, parallel ? -1 : lines[!r.vertical].y); for (auto& l : lines) { long long line = board[l.vertical][l.y]; long long mask = (1ll << r.length) - 1; for (int x = r.length; x <= N; x += 2) { long long n = __builtin_ctzll(line); x += (int)n; line >>= n; n = __builtin_popcountll(line & mask); if (bn < n) { bn = n; r.vertical = l.vertical; r.y = l.y; r.x = min(N, x) - r.length; } line >>= 2; } } flip2(r, parallel ? -1 : lines[!r.vertical].y); if (bn != cn) { updated = true; last = r.id; } else if (last == r.id) break; } if (!updated) break; } int diff = (int)(__builtin_popcountll(lines[0].line) + __builtin_popcountll(lines[1].line) - (!parallel && lines[0].line >> lines[1].y & 1) - __builtin_popcountll(board[lines[0].vertical][lines[0].y]) - __builtin_popcountll(board[lines[1].vertical][lines[1].y]) + (!parallel && board[lines[0].vertical][lines[0].y] >> lines[1].y & 1)); if (rando.nextDouble() < exp(diff * heat)) { score += diff; lineToIndicies[lines[0].vertical][lines[0].y].resize(s0); lineToIndicies[lines[1].vertical][lines[1].y].resize(s1); lines[0].line = lines[1].line = 0; for (int i = 0; i < (int)indicies.size(); ++i) { auto& r = states[indicies[i]]; for (int j = 0; j < 2; ++j) { int k = r.vertical == lines[1].vertical && r.y == lines[1].y; lines[k].line ^= ((1ll << r.length) - 1) << r.x; if (!parallel && (unsigned)lines[!r.vertical].y - r.x < (unsigned)r.length) lines[k].line ^= 1ll << lines[!r.vertical].y; if (j == 0) r = rectangles[i]; else lineToIndicies[r.vertical][r.y].emplace_back(indicies[i]); } } for (auto& l : lines) { long long mask = 1ll << l.y; while (l.line) { long long x = __builtin_ctzll(l.line); board[!l.vertical][x] ^= mask; l.line ^= 1ll << x; } } if (bestScore < score) { bestScore = score; bestStates = states; } } else { board[lines[0].vertical][lines[0].y] = lines[0].line; board[lines[1].vertical][lines[1].y] = lines[1].line; } } score = bestScore; states.swap(bestStates); for (auto& r : states) { if (r.vertical) { for (int x = r.x; x < r.x + r.length; ++x) A[x][r.y] ^= 1; } else { for (int x = r.x; x < r.x + r.length; ++x) A[r.y][x] ^= 1; } } for (int y = 0; y < N; ++y) { for (int x = 0; x < N; ++x) { if (y && A[y][x] && A[y - 1][x] && a2.size()) { A[y][x] = A[y - 1][x] = false; states.emplace_back(true, y - 1, x, 2, a2.back()); a2.pop_back(); } else if (x && A[y][x] && A[y][x - 1] && a2.size()) { A[y][x] = A[y][x - 1] = false; states.emplace_back(false, x - 1, y, 2, a2.back()); a2.pop_back(); } } } for (int y = 0; y < N; ++y) { for (int x = 0; x < N; ++x) { if (A[y][x]) continue; for (int i = 1; i < 4; ++i) { int x2 = x + dx[i]; int y2 = y + dy[i]; if (x2 < 0 || N <= x2 || y2 < 0 || N <= y2 || !A[y2][x2]) continue; for (int j = 0; j < i; ++j) { int x3 = x + dx[j]; int y3 = y + dy[j]; if (x3 < 0 || N <= x3 || y3 < 0 || N <= y3 || !A[y3][x3] || a2.size() < 2) continue; A[y2][x2] = A[y3][x3] = false; score -= 2; if (i % 2) states.emplace_back(true, min(y, y2), x, 2, a2.back()); else states.emplace_back(false, min(x, x2), y, 2, a2.back()); a2.pop_back(); if (j % 2) states.emplace_back(true, min(y, y3), x, 2, a2.back()); else states.emplace_back(false, min(x, x3), y, 2, a2.back()); a2.pop_back(); break; } } } } score -= (int)a2.size() * 2; for (int y = 0; y < N && a2.size(); ++y) { for (int x = 0; x < N && a2.size(); ++x) { if (y && A[y][x] != A[y - 1][x]) { for (; a2.size(); a2.pop_back()) { A[y][x] ^= 1; A[y - 1][x] ^= 1; states.emplace_back(true, y - 1, x, 2, a2.back()); } } if (x && A[y][x] != A[y][x - 1]) { for (; a2.size(); a2.pop_back()) { A[y][x] ^= 1; A[y][x - 1] ^= 1; states.emplace_back(false, x - 1, y, 2, a2.back()); } } } } for (int y = 0; y < N; ++y) { for (int x = 0; x < N; ++x) { if (A[y][x] && a1.size()) { states.emplace_back(false, x, y, 1, a1.back()); a1.pop_back(); } } } sort(states.begin(), states.end(), [](const Rectangle& a, const Rectangle& b) { return a.id < b.id; }); for (auto& r : states) { if (r.vertical) swap(r.x, r.y); cout << r.y + 1 << ' ' << r.x + 1 << ' ' << r.y + 1 << ' ' << r.x + r.length << endl; } return 0; }