結果
問題 | No.5002 stick xor |
ユーザー | kurenai3110 |
提出日時 | 2018-05-26 02:18:27 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 905 ms / 1,000 ms |
コード長 | 6,723 bytes |
コンパイル時間 | 31,598 ms |
実行使用メモリ | 1,704 KB |
スコア | 43,881 |
最終ジャッジ日時 | 2018-05-26 02:19:01 |
ジャッジサーバーID (参考情報) |
judge10 / |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 905 ms
1,704 KB |
testcase_01 | AC | 904 ms
1,704 KB |
testcase_02 | AC | 905 ms
1,704 KB |
testcase_03 | AC | 905 ms
1,700 KB |
testcase_04 | AC | 905 ms
1,696 KB |
testcase_05 | AC | 904 ms
1,700 KB |
testcase_06 | AC | 904 ms
1,696 KB |
testcase_07 | AC | 905 ms
1,704 KB |
testcase_08 | AC | 904 ms
1,704 KB |
testcase_09 | AC | 904 ms
1,700 KB |
testcase_10 | AC | 905 ms
1,704 KB |
testcase_11 | AC | 905 ms
1,700 KB |
testcase_12 | AC | 904 ms
1,700 KB |
testcase_13 | AC | 905 ms
1,704 KB |
testcase_14 | AC | 905 ms
1,700 KB |
testcase_15 | AC | 904 ms
1,704 KB |
testcase_16 | AC | 904 ms
1,704 KB |
testcase_17 | AC | 904 ms
1,700 KB |
testcase_18 | AC | 905 ms
1,696 KB |
testcase_19 | AC | 904 ms
1,704 KB |
testcase_20 | AC | 905 ms
1,704 KB |
testcase_21 | AC | 903 ms
1,700 KB |
testcase_22 | AC | 905 ms
1,700 KB |
testcase_23 | AC | 905 ms
1,700 KB |
testcase_24 | AC | 905 ms
1,696 KB |
testcase_25 | AC | 904 ms
1,700 KB |
testcase_26 | AC | 905 ms
1,700 KB |
testcase_27 | AC | 905 ms
1,700 KB |
testcase_28 | AC | 905 ms
1,700 KB |
testcase_29 | AC | 904 ms
1,704 KB |
testcase_30 | AC | 904 ms
1,696 KB |
testcase_31 | AC | 905 ms
1,700 KB |
ソースコード
#include <iostream> #include <algorithm> #include <vector> #include <string> #include <chrono> using namespace std; class Timer { chrono::high_resolution_clock::time_point start, end; double limit; public: Timer() { start = chrono::high_resolution_clock::now(); } Timer(double l) { start = chrono::high_resolution_clock::now(); limit = l; } double getTime() { end = chrono::high_resolution_clock::now(); return chrono::duration<double>(end - start).count(); } bool Over() { if (getTime() > limit) { return true; } return false; } void setLimit(double l) { limit = l; } void setStart() { start = chrono::high_resolution_clock::now(); } double getLimit() { return limit; } }; class Xor128 { unsigned static int x, y, z, w; public: Xor128() { x = 31103110, y = 123456789, z = 521288629, w = 88675123; } unsigned int rand() { unsigned int t; t = (x ^ (x << 11)); x = y; y = z; z = w; return(w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))); } }; unsigned int Xor128::x, Xor128::y, Xor128::z, Xor128::w; const double TIMELIMIT = 0.9; class Solver{ int N, K; int L[500]; char A[60][60]; int sumA0[61][61], sumA1[61][61]; Timer tmr; Xor128 xor128; vector<pair<char, pair<int, int>>>ans, best_ans; int best_score; public: void input() { cin >> N >> K; for (int i = 0; i < K; i++)cin >> L[i]; for (int i = 0; i < N; i++)for (int j = 0; j < N; j++) { cin >> A[i][j]; A[i][j] -= '0'; } } void init() { input(); tmr.setStart(); for (int i = 0; i <= N; i++) { for (int j = 0; j <= N; j++) { sumA0[i][j] = sumA1[i][j] = 0; } } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { sumA0[i + 1][j] += sumA0[i][j] + A[i][j]; sumA1[i][j + 1] += sumA1[i][j] + A[i][j]; } } ans.resize(K, make_pair(-1, make_pair(0, 0))); best_score = 0; for (int i = 0; i < K; i++) { best_score += scoring(0, 0, 0, i); ans[i].first = 0; update(0, 0, 0, i); } best_ans = ans; tmr.setLimit(TIMELIMIT); } void SA() { double startTemp = 1, endTemp = 0.05; double diffTemp = (endTemp - startTemp) / TIMELIMIT; double current_time = tmr.getTime(); int score = best_score; int loop = 0; int i = 0; while (current_time < TIMELIMIT) { loop++; if (loop % 1000 == 0) { current_time = tmr.getTime(); } int change = -1e9; bool mode; int r, c; for (int t = 0; t < L[i] + 2; t++) { bool tmode = xor128.rand() % 2; int tr = xor128.rand() % (N - L[i] + 1); int tc = xor128.rand() % N; if (tmode)swap(tr, tc); if (t == 0) { tmode = ans[i].first; tr = ans[i].second.first; tc = ans[i].second.second; if (tmode) { tc -= 1; if (tc < 0)continue; } else { tr -= 1; if (tr < 0)continue; } } else if (t == 1) { tmode = ans[i].first; tr = ans[i].second.first; tc = ans[i].second.second; if (tmode) { tc += 1; if (tc >= (N - L[i] + 1))continue; } else { tr += 1; if (tr >= (N - L[i] + 1))continue; } } int tmp = scoring(tmode, tr, tc, i); if (t < 2) if(current_time < TIMELIMIT*0.8)continue; if (tmp >= change) { mode = tmode; r = tr; c = tc; change = tmp; } } bool accept = false; if (change >= 0)accept = true; else if (change < -2)accept = false; else { double temp = startTemp + diffTemp * tmr.getTime(); double prob = exp(change / temp); accept = prob * UINT32_MAX > xor128.rand(); } if (accept) { score += change; update(ans[i].first, ans[i].second.first, ans[i].second.second, i); ans[i].first = mode; ans[i].second.first = r; ans[i].second.second = c; update(mode, r, c, i); if (score > best_score) { //cerr << current_time << " " << best_score << endl; best_score = score; best_ans = ans; } } i = (i + 1) % K; } cerr << tmr.getTime() << endl; cerr << loop << endl; cerr << best_score << endl; } int scoring(int mode, int r, int c, int i) { int change = 0; if (ans[i].first != -1) { int r = ans[i].second.first; int c = ans[i].second.second; int mode = ans[i].first; if (mode) change += (sumA1[r][c + L[i]] - sumA1[r][c]); else change += (sumA0[r + L[i]][c] - sumA0[r][c]); } if (mode) change += (sumA1[r][c + L[i]] - sumA1[r][c]); else change += (sumA0[r + L[i]][c] - sumA0[r][c]); change -= L[i]; int r1, r2; r1 = r; r2 = ans[i].second.first; int c1, c2; c1 = c; c2 = ans[i].second.second; if (mode == ans[i].first) { if (mode == true && r1 == r2) { if (c1 > c2)swap(c1, c2); if (c1 + L[i] > c2)change += ((c1 + L[i] - c2) - 2 * (sumA1[r][c1 + L[i]] - sumA1[r][c2])); } if (mode == false && c1 == c2) { if (r1 > r2)swap(r1, r2); if (r1 + L[i] > r2)change += ((r1 + L[i] - r2) - 2 * (sumA0[r1 + L[i]][c] - sumA0[r2][c])); } } else if (ans[i].first != -1) { if (mode) { if (c1 <= c2 && c2 <= c1 + L[i] - 1 && r2 <= r1 && r1 <= r2 + L[i] - 1) { change -= (A[r1][c2] ? 1 : -1); } } else { if (r1 <= r2 && r2 <= r1 + L[i] - 1 && c2 <= c1 && c1 <= c2 + L[i] - 1) { change -= (A[r2][c1] ? 1 : -1); } } } change *= 2; if (ans[i].first == -1)change += L[i]; return change; } void update(int mode, int r, int c, int i) { int rev_mode = mode ^ 1; if (mode) { int p = 0; for (int j = c; j < c + L[i]; j++) { if(mode)sumA1[r][j] += p; else sumA0[r][j] += p; int p2 = (A[r][j] ? -1 : 1); for (int k = r + 1; k <= N; k++) { if(rev_mode)sumA1[k][j] += p2; else sumA0[k][j] += p2; } p += (A[r][j] ? -1 : 1); A[r][j] ^= 1; } for (int j = c + L[i]; j <= N; j++) { if (mode)sumA1[r][j] += p; else sumA0[r][j] += p; } } else { int p = 0; for (int j = r; j < r + L[i]; j++) { if (mode)sumA1[j][c] += p; else sumA0[j][c] += p; int p2 = (A[j][c] ? -1 : 1); for (int k = c + 1; k <= N; k++) { if(rev_mode)sumA1[j][k] += p2; else sumA0[j][k] += p2; } p += (A[j][c] ? -1 : 1); A[j][c] ^= 1; } for (int j = r + L[i]; j <= N; j++) { if (mode)sumA1[j][c] += p; else sumA0[j][c] += p; } } } void output() { for (int i = 0; i < K; i++) { cout << best_ans[i].second.first + 1 << " " << best_ans[i].second.second + 1 << " "; if (best_ans[i].first)cout << best_ans[i].second.first + 1 << " " << best_ans[i].second.second + L[i] << endl; else cout << best_ans[i].second.first + L[i] << " " << best_ans[i].second.second + 1 << endl; } } void run() { init(); SA(); output(); } }; int main() { Solver slv; slv.run(); return 0; }