結果
問題 | No.5006 Hidden Maze |
ユーザー | wanui |
提出日時 | 2022-06-12 20:57:32 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 59 ms / 2,000 ms |
コード長 | 12,651 bytes |
コンパイル時間 | 3,232 ms |
実行使用メモリ | 22,728 KB |
スコア | 66,164 |
平均クエリ数 | 339.36 |
最終ジャッジ日時 | 2022-06-12 20:57:44 |
合計ジャッジ時間 | 12,543 ms |
ジャッジサーバーID (参考情報) |
judge11 / judge15 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 27 ms
22,276 KB |
testcase_01 | AC | 32 ms
22,692 KB |
testcase_02 | AC | 56 ms
21,780 KB |
testcase_03 | AC | 25 ms
21,768 KB |
testcase_04 | AC | 26 ms
21,916 KB |
testcase_05 | AC | 31 ms
21,904 KB |
testcase_06 | AC | 27 ms
22,576 KB |
testcase_07 | AC | 57 ms
22,576 KB |
testcase_08 | AC | 30 ms
22,264 KB |
testcase_09 | AC | 28 ms
21,916 KB |
testcase_10 | AC | 36 ms
21,792 KB |
testcase_11 | AC | 28 ms
22,276 KB |
testcase_12 | AC | 31 ms
22,228 KB |
testcase_13 | AC | 25 ms
22,704 KB |
testcase_14 | AC | 55 ms
21,940 KB |
testcase_15 | AC | 24 ms
22,016 KB |
testcase_16 | AC | 24 ms
21,940 KB |
testcase_17 | AC | 24 ms
21,792 KB |
testcase_18 | AC | 26 ms
21,904 KB |
testcase_19 | AC | 27 ms
21,952 KB |
testcase_20 | AC | 25 ms
22,072 KB |
testcase_21 | AC | 25 ms
21,780 KB |
testcase_22 | AC | 24 ms
22,004 KB |
testcase_23 | AC | 25 ms
22,632 KB |
testcase_24 | AC | 31 ms
22,288 KB |
testcase_25 | AC | 26 ms
22,704 KB |
testcase_26 | AC | 56 ms
22,276 KB |
testcase_27 | AC | 26 ms
21,612 KB |
testcase_28 | AC | 24 ms
21,904 KB |
testcase_29 | AC | 25 ms
22,600 KB |
testcase_30 | AC | 24 ms
22,612 KB |
testcase_31 | AC | 24 ms
21,892 KB |
testcase_32 | AC | 37 ms
22,600 KB |
testcase_33 | AC | 30 ms
21,952 KB |
testcase_34 | AC | 34 ms
22,228 KB |
testcase_35 | AC | 26 ms
21,992 KB |
testcase_36 | AC | 25 ms
21,952 KB |
testcase_37 | AC | 58 ms
21,904 KB |
testcase_38 | AC | 26 ms
22,456 KB |
testcase_39 | AC | 26 ms
21,916 KB |
testcase_40 | AC | 26 ms
22,620 KB |
testcase_41 | AC | 24 ms
21,940 KB |
testcase_42 | AC | 28 ms
21,768 KB |
testcase_43 | AC | 24 ms
22,004 KB |
testcase_44 | AC | 24 ms
21,768 KB |
testcase_45 | AC | 30 ms
21,952 KB |
testcase_46 | AC | 57 ms
22,264 KB |
testcase_47 | AC | 25 ms
22,228 KB |
testcase_48 | AC | 29 ms
21,780 KB |
testcase_49 | AC | 58 ms
22,728 KB |
testcase_50 | AC | 27 ms
21,940 KB |
testcase_51 | AC | 27 ms
21,892 KB |
testcase_52 | AC | 30 ms
21,892 KB |
testcase_53 | AC | 34 ms
21,928 KB |
testcase_54 | AC | 25 ms
22,004 KB |
testcase_55 | AC | 30 ms
22,588 KB |
testcase_56 | AC | 29 ms
22,588 KB |
testcase_57 | AC | 33 ms
21,940 KB |
testcase_58 | AC | 28 ms
21,952 KB |
testcase_59 | AC | 25 ms
21,928 KB |
testcase_60 | AC | 27 ms
22,564 KB |
testcase_61 | AC | 24 ms
22,016 KB |
testcase_62 | AC | 27 ms
22,468 KB |
testcase_63 | AC | 57 ms
21,952 KB |
testcase_64 | AC | 31 ms
21,952 KB |
testcase_65 | AC | 25 ms
21,928 KB |
testcase_66 | AC | 26 ms
21,940 KB |
testcase_67 | AC | 25 ms
21,792 KB |
testcase_68 | AC | 33 ms
21,904 KB |
testcase_69 | AC | 24 ms
21,928 KB |
testcase_70 | AC | 24 ms
22,612 KB |
testcase_71 | AC | 25 ms
21,904 KB |
testcase_72 | AC | 26 ms
21,940 KB |
testcase_73 | AC | 27 ms
21,928 KB |
testcase_74 | AC | 25 ms
21,940 KB |
testcase_75 | AC | 58 ms
21,808 KB |
testcase_76 | AC | 31 ms
22,588 KB |
testcase_77 | AC | 39 ms
21,928 KB |
testcase_78 | AC | 24 ms
21,992 KB |
testcase_79 | AC | 59 ms
21,804 KB |
testcase_80 | AC | 26 ms
22,632 KB |
testcase_81 | AC | 25 ms
22,004 KB |
testcase_82 | AC | 29 ms
21,904 KB |
testcase_83 | AC | 23 ms
21,780 KB |
testcase_84 | AC | 25 ms
21,768 KB |
testcase_85 | AC | 37 ms
22,456 KB |
testcase_86 | AC | 26 ms
22,004 KB |
testcase_87 | AC | 57 ms
22,576 KB |
testcase_88 | AC | 59 ms
22,016 KB |
testcase_89 | AC | 50 ms
22,456 KB |
testcase_90 | AC | 25 ms
21,588 KB |
testcase_91 | AC | 25 ms
21,992 KB |
testcase_92 | AC | 25 ms
21,952 KB |
testcase_93 | AC | 24 ms
22,612 KB |
testcase_94 | AC | 35 ms
21,952 KB |
testcase_95 | AC | 29 ms
22,576 KB |
testcase_96 | AC | 29 ms
21,892 KB |
testcase_97 | AC | 45 ms
21,940 KB |
testcase_98 | AC | 49 ms
22,276 KB |
testcase_99 | AC | 27 ms
21,904 KB |
ソースコード
#include <bits/stdc++.h> // clang-format off using namespace std; using ll=long long; using ull=unsigned long long; using pll=pair<ll,ll>; const ll INF=4e18; void print0(){}; template<typename H,typename... T> void print0(H h,T... t){cout<<h;print0(t...);} void print(){print0("\n");}; template<typename H,typename... T>void print(H h,T... t){print0(h);if(sizeof...(T)>0)print0(" ");print(t...);} void perr0(){}; template<typename H,typename... T> void perr0(H h,T... t){cerr<<h;perr0(t...);} void perr(){perr0("\n");}; template<typename H,typename... T>void perr(H h,T... t){perr0(h);if(sizeof...(T)>0)perr0(" ");perr(t...);} void ioinit() { cout<<fixed<<setprecision(15); cerr<<fixed<<setprecision(6); ios_base::sync_with_stdio(0); cin.tie(0); } // clang-format on const int LOCAL = 0; using pii = pair<int, int>; using tii = tuple<int, int, int>; struct point { int i; int j; }; bool operator==(const point &lhs, const point &rhs) { return (lhs.i == rhs.i && lhs.j == rhs.j); } bool operator!=(const point &lhs, const point &rhs) { return !(lhs == rhs); } bool operator<(const point &lhs, const point &rhs) { if (lhs.i != rhs.i) { return lhs.i < rhs.i; } return lhs.j < rhs.j; } std::ostream &operator<<(std::ostream &os, point &pt) { string s; s.push_back('('); s = s + to_string(pt.i); s = s + ", "; s = s + to_string(pt.j); s.push_back(')'); return os << s; } mt19937 engine(0); clock_t start_time; double now() { return 1000.0 * (clock() - start_time) / CLOCKS_PER_SEC; } void marathon_init() { start_time = clock(); random_device seed_gen; engine.seed(seed_gen()); } int randint(int mn, int mx) { int rng = mx - mn + 1; return mn + (engine() % rng); } double uniform(double x, double y) { const int RND = 1e8; double mean = (x + y) / 2.0; double dif = y - mean; double p = double(engine() % RND) / RND; return mean + dif * (1.0 - 2.0 * p); } bool anneal_accept(double new_score, double old_score, double cur_time, double begin_time, double end_time, double begin_temp, double end_temp) { const int ANNEAL_RND = 1e8; const double ANNEAL_EPS = 1e-6; double temp = cur_time * (end_temp - begin_temp) / (end_time - begin_time) + (end_time * begin_temp - end_temp * begin_time) / (end_time - begin_time); return (exp((new_score - old_score) / temp) > double(engine() % ANNEAL_RND) / ANNEAL_RND + ANNEAL_EPS); } const int N = 20; double P; const int R = 0; const int D = 1; const int L = 2; const int U = 3; vector<point> mvs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; int c2d(char c) { if (c == 'R') return R; if (c == 'D') return D; if (c == 'L') return L; if (c == 'U') return U; return -1; } char d2c(int d) { if (d == R) return 'R'; if (d == D) return 'D'; if (d == L) return 'L'; if (d == U) return 'U'; return '?'; } vector<point> l_table[N][N]; int l_btable[N][N]; bool l_check_table() { queue<point> que; que.push({0, 0}); vector<vector<bool>> done(N, vector<bool>(N)); while (que.size()) { point p = que.front(); que.pop(); if (done[p.i][p.j]) continue; done[p.i][p.j] = true; for (auto mv : l_table[p.i][p.j]) { int ni = p.i + mv.i; int nj = p.j + mv.j; que.push({ni, nj}); } } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (!done[i][j]) return false; } } return true; } void l_maketable(int M) { if (!LOCAL) return; while (true) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { l_table[i][j].clear(); l_btable[i][j] = 0; } } set<tii> wallset; int nwall = 0; while (nwall < M) { if (randint(0, 1) == 0) { // 右 int i = randint(0, N - 1); int j = randint(0, N - 2); tii w = {0, i, j}; if (wallset.count(w)) continue; wallset.insert(w); } else { // 下 int i = randint(0, N - 2); int j = randint(0, N - 1); tii w = {1, i, j}; if (wallset.count(w)) continue; wallset.insert(w); } nwall++; } // RDLU の順 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (i + 1 < N && !wallset.count({1, i, j})) { l_table[i][j].push_back({1, 0}); //下 l_btable[i][j] += (1 << D); } if (i - 1 >= 0 && !wallset.count({1, i - 1, j})) { l_table[i][j].push_back({-1, 0}); //上 l_btable[i][j] += (1 << U); } if (j + 1 < N && !wallset.count({0, i, j})) { l_table[i][j].push_back({0, 1}); //右 l_btable[i][j] += (1 << R); } if (j - 1 >= 0 && !wallset.count({0, i, j - 1})) { l_table[i][j].push_back({0, -1}); //左 l_btable[i][j] += (1 << L); } } } if (!l_check_table()) continue; perr("M=", M); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { perr0("・"); if (j + 1 < N && wallset.count({0, i, j})) { perr0("│"); } else { perr0(" "); } } perr0("\n"); for (int j = 0; j < N; j++) { if (i + 1 < N && wallset.count({1, i, j})) { perr0("─"); } else { perr0(" "); } perr0(" "); } perr0("\n"); } break; } } int request(string ops) { cout << ops << endl; if (!LOCAL) { int res; cin >> res; return res; } { bool hitwall = false; point cur = {0, 0}; point goal = {N - 1, N - 1}; for (auto op : ops) { int d = 0; if (op == 'R') { d = R; } else if (op == 'D') { d = D; } else if (op == 'L') { d = L; } else if (op == 'U') { d = U; } else { perr(ops, "!?!?"); assert(false); } if (!(l_btable[cur.i][cur.j] & (1 << d))) { hitwall = true; break; } auto mv = mvs[d]; cur = {cur.i + mv.i, cur.j + mv.j}; } if (!hitwall && cur == goal) { return -1; } } { int opnum = 0; point cur = {0, 0}; for (auto op : ops) { int d = c2d(op); if (!(l_btable[cur.i][cur.j] & (1 << d))) { return opnum; } if (uniform(0.0, 1.0) < P) { return opnum; } auto mv = mvs[d]; cur = {cur.i + mv.i, cur.j + mv.j}; opnum++; } return opnum; } } string rand_combination(string s0, int start_ind) { string s = s0; int r = 0; int d = 0; for (int j = 0; j < start_ind; j++) { if (s[j] == 'R') r++; if (s[j] == 'D') d++; } for (int i = start_ind; i < int(s.size()); i++) { if (r < N - 1 && d < N - 1) { if (randint(0, 1)) { s[i] = 'R'; r++; } else { s[i] = 'D'; d++; } } else if (r < N - 1) { s[i] = 'R'; r++; } else { s[i] = 'D'; d++; } } return s; } string makeop(int opid, vector<vector<string>> &history, unordered_set<string> &hist_ops) { // とりあえず R と D だけ。それで到達できないケースは諦める。 int N2 = 2 * N - 2; int maxlen = 0; // 全探索モード do { int BRUTE_FORCE_START; if (P < 0.071) { BRUTE_FORCE_START = 32; } else if (P < 0.101) { BRUTE_FORCE_START = 30; } else { BRUTE_FORCE_START = 28; } point maxpt = {0, 0}; for (int i = 0; i < N-2; i++) { for (int j = 0; j < N-2; j++) { if (history[i][j].size() == 0) continue; int len = i + j; if (maxlen < len) { maxlen = len; maxpt = {i, j}; } } } if (maxlen < BRUTE_FORCE_START) { break; } int baseind = maxlen + 1; int brute_force_num = N2 - baseind; int r0 = 0; int d0 = 0; { string s = history[maxpt.i][maxpt.j]; for (int j = 0; j < baseind; j++) { if (s[j] == 'R') r0++; if (s[j] == 'D') d0++; } } for (int i = 0; i < (1 << brute_force_num); i++) { string s = history[maxpt.i][maxpt.j]; int r = r0; int d = d0; for (int j = 0; j < brute_force_num; j++) { char c; if ((i >> j) & 1) { c = 'R'; r++; } else { c = 'D'; d++; } s[j + baseind] = c; } if (r > N - 1 || d > N - 1) continue; if (hist_ops.count(s)) continue; return s; } } while (0); // 完全な無作為 if (opid < 20) { string s; s.resize(N2); return rand_combination(s, 0); } // 適当にサンプリング+改変 { vector<pair<double, point>> sample_candidate; for (int si = 0; si < N; si++) { for (int sj = 0; sj < N; sj++) { if (history[si][sj].size() == 0) continue; int ok = 0; ok += (si + 1 < N && history[si + 1][sj].size() == 0); ok += (sj + 1 < N && history[si][sj + 1].size() == 0); if (ok) { double score = (si + sj) * (si + sj) * (si + sj) - abs(si - sj); sample_candidate.push_back({score, {si, sj}}); } } } sort(sample_candidate.begin(), sample_candidate.end(), [](pair<double, point> a, pair<double, point> b) { return a.first > b.first; }); point sample = sample_candidate[0].second; double total = 0; for (auto c : sample_candidate) { total += c.first; } double rat = uniform(0.0, total); double cum = 0; for (auto c : sample_candidate) { cum += c.first; if (rat < cum) { sample = c.second; break; } } // 後ろの方を適当に改変 string sample_str = history[sample.i][sample.j]; int sz = sample_str.size(); int changestart = (sample.i + sample.j) + (-1); if (changestart < 0) changestart = 0; return rand_combination(sample_str, changestart); } return "RDRD"; } void solve() { int opslimit = 1001; if (LOCAL) opslimit = 1000; unordered_set<string> hist_ops; vector<vector<string>> history(N, vector<string>(N, "")); for (int opid = 1; opid <= opslimit; opid++) { string s = makeop(opid, history, hist_ops); int res = request(s); if (res < 0) { perr(opid, "success!"); perr0("score=", 1001 - opid, "\n"); return; } { point cur = {0, 0}; for (int i = 0; i < res; i++) { char c = s[i]; auto mv = mvs[c2d(c)]; point nxt = {cur.i + mv.i, cur.j + mv.j}; if (history[nxt.i][nxt.j].size() == 0) { history[nxt.i][nxt.j] = s; } cur = nxt; } } if (LOCAL) { perr(res); } } perr(opslimit, "failure!"); perr0("score=0\n"); } int main() { marathon_init(); ioinit(); int _h, _w; cin >> _h >> _w >> P; P *= 0.01; int M = 200; if (LOCAL) { cin >> M; } perr("P=", P); l_maketable(M); solve(); return 0; }