結果

問題 No.5022 XOR Printer
ユーザー Akidai
提出日時 2025-07-26 16:51:30
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 1,768 ms / 2,000 ms
コード長 10,923 bytes
コンパイル時間 4,683 ms
コンパイル使用メモリ 268,776 KB
実行使用メモリ 7,720 KB
スコア 5,201,947,027
最終ジャッジ日時 2025-07-26 16:53:15
合計ジャッジ時間 96,678 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 50
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
using ll = long long;
constexpr ll mod = 1e9 + 7;
constexpr ll INF = (1LL << 62) - (1LL << 31) - 1;

#define REP(i, init, n) for(int i = (int)(init); i < (int)(n); i++)
#define RREP(i, init, n) for(int i = (int)(init); i >= (int)(n); i--)
#define All(A) A.begin(), A.end()
#define rAll(A) A.rbegin(), A.rend()

#define vi vector<int>
#define vl vector<long>
#define vvi vector<vector<int>>
#define vvl vector<vector<long>>
#define pint pair<int, int>
#define plong pair<long, long>

int N, T;
vvi A;


namespace Annealing {
    bool is_online_judge() {
        return true;
    }

    class TimeKeeper {
        public:
            std::chrono::high_resolution_clock::time_point m_start_time;
            int64_t m_time_threshold;
            int64_t dev_env_threshold;
            int dev_const = 1;
            TimeKeeper(): m_start_time(std::chrono::high_resolution_clock::now()) {
                if(!is_online_judge()) {
                    dev_const = 1;
                }
            }
            void set_time_threshold(const int64_t &time_threshold) {
                m_time_threshold = time_threshold;
                dev_env_threshold = time_threshold * dev_const;
            }
            bool is_time_over() {
                using std::chrono::duration_cast;
                using std::chrono::milliseconds;
                auto diff = std::chrono::high_resolution_clock::now() - (this->m_start_time);
                return duration_cast<milliseconds>(diff).count() >= time_threshold();
            }

            int cur_time() {
                using std::chrono::duration_cast;
                using std::chrono::milliseconds;
                auto diff = std::chrono::high_resolution_clock::now() - (this->m_start_time);
                return duration_cast<milliseconds>(diff).count();
            }

            long double elapsed_ratio() {
                return (long double)(this -> cur_time()) / time_threshold();
            }

            int64_t time_threshold() {
                if(!is_online_judge()) {
                    return dev_env_threshold;
                }
                return m_time_threshold;
            }
    };

    class Temperature {
        private:
            long double m_initial_temperature;
            long double m_last_temperature;
            int init_elapsed;
            TimeKeeper tk;
        public:
            Temperature(const long double &initial_temperature, const long double &last_temperature, const TimeKeeper &tk):
                m_initial_temperature(initial_temperature),
                m_last_temperature(last_temperature),
                tk(tk) {
                    init_elapsed = this->tk.cur_time();
                }

            long double get_temperature() {
                long double ratio = (long double)(tk.cur_time() - init_elapsed) / (tk.time_threshold() - init_elapsed);
                return m_initial_temperature + (m_last_temperature - m_initial_temperature) * ratio;
            }

            long double prob(const long double &delta) {
                return exp(-delta / get_temperature());
            }

            bool changed(const long double &delta) {
                return (delta <= 0) || (rand() < prob(delta) * RAND_MAX);
            }
    };
}

int calc_dist(const pint &a, const pint &b) {
    return abs(a.first - b.first) + abs(a.second - b.second);
}

int calc_score(pint &cur, vector<pint> &targets, vvi &shelter_map) {
    pint last = targets.back();
    if(shelter_map[last.first][last.second] == 1) {
        return 1 << 30;
    }

    int score = calc_dist(cur, targets[0]);
    REP(i, 0, targets.size() - 1) {
        score += calc_dist(targets[i], targets[i + 1]);
    }
    return score;
}

long calc_score2(int b, int s, int rest, pint &cur, vector<pint> &targets) {
    long score = 0;
    int turn = calc_dist(cur, targets[0]);
    if(turn + 1 > rest) {
        return score;
    }
    score += ((A[targets[0].first][targets[0].second] ^ s) & ((1 << b) - 1));
    turn++;
    REP(i, 1, targets.size()) {
        turn += calc_dist(targets[i - 1], targets[i]);
        if(turn + 1 > rest) {
            break;
        }
        score += ((A[targets[i].first][targets[i].second] ^ s) & ((1 << b) - 1));
        turn++;
    }
    if(score >= 200000) {
        return 0;
    } 
    return score;
}

void move_U(pint &cur, string &ans) {
    cur.first--;
    ans += 'U';
}
void move_D(pint &cur, string &ans) {
    cur.first++;
    ans += 'D';
}
void move_L(pint &cur, string &ans) {
    cur.second--;
    ans += 'L';
}
void move_R(pint &cur, string &ans) {
    cur.second++;
    ans += 'R';
}
void write(int &s, pint &cur, string &ans) {
    A[cur.first][cur.second] ^= s;
    ans += 'W';
}
void copy(int &s, pint &cur, string &ans) {
    s ^= A[cur.first][cur.second];
    ans += 'C';
}
void move(pint &cur, const pint &next, string &ans) {
    while(cur != next) {
        if(cur.first < next.first) {
            move_D(cur, ans);
        } else if(cur.first > next.first) {
            move_U(cur, ans);
        } else if(cur.second < next.second) {
            move_R(cur, ans);
        } else if(cur.second > next.second) {
            move_L(cur, ans);
        }
    }
}


void solve() {
    pint cur = {0, 0};
    int s = 0;
    int move_count = 0;
    string ans = "";
    vector<pint> shelters;
    vvi shelters_map(N, vi(N, 0));

    Annealing::TimeKeeper tk;
    mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());

    RREP(b, 19, 10) {
        int mask = (1 << b);
        int min_dist = 100;
        pint next_target = {-1, -1};
        // cerr << "cur: " << cur.first << " " << cur.second << " s: " << s << " mask: " << bitset<20>(mask) << endl;
        REP(i, 0, N) {
            REP(j, 0, N) {
                if(shelters_map[i][j] == 1) continue;
                if(s & mask) {
                    if((A[i][j] & mask) == 0) {
                        int dist = calc_dist(cur, {i, j});
                        if(dist < min_dist) {
                            min_dist = dist;
                            next_target = {i, j};
                        }
                    }
                } else {
                    if(A[i][j] & mask) {
                        int dist = calc_dist(cur, {i, j});
                        if(dist < min_dist) {
                            min_dist = dist;
                            next_target = {i, j};
                        }
                    }
                }
            }
        }
        // cerr << "next_target: " << next_target.first << " " << next_target.second << endl;

        if(next_target.first == -1) {
            break;
        }
        move(cur, next_target, ans);
        copy(s, cur, ans);
        if(ans.size() >= T) break;

        cerr << b << " " << cur.first << " " << cur.second << " " << s << endl;
        cerr << bitset<20>(s) << endl;
    
        vvi board(N, vi(N, 0));
        int rest = 0;
        vector<pint> targets;
        REP(i, 0, N) {
            REP(j, 0, N) {
                if(A[i][j] & mask) {
                    board[i][j] = 1;
                } else {
                    targets.push_back({i, j});
                    rest++;
                }
            }
        }
        tk.set_time_threshold(196 * (20 - b));
        Annealing::Temperature temp(10, 0, tk);
        int best_score = calc_score(cur, targets, shelters_map);
        int cur_score = best_score;

        int itr = 0, update_cnt = 0;
        while(!tk.is_time_over()) {
            int a = mt() % targets.size();
            int b = mt() % targets.size();
            if(a == b) continue;
            itr++;

            swap(targets[a], targets[b]);
            int new_score = calc_score(cur, targets, shelters_map);

            if(temp.changed(new_score - cur_score)) {
                update_cnt++;
                cur_score = new_score;
                if(new_score < best_score) {
                    best_score = new_score;
                }
            } else {
                swap(targets[a], targets[b]);
            }
        }
        cerr << "itr: " << itr << " update_cnt: " << update_cnt << " best_score: " << best_score << " targets: " << targets.size() << endl;
        if(best_score + targets.size() + ans.size() >= T && b >= 11) {
            cerr << "final optimization" << endl;
            tk.set_time_threshold(196 * (20 - b + 1));
            int rest_turn = T - ans.size();
            Annealing::Temperature temp2(2000, 0, tk);
            long best_score2 = calc_score2(b, s, rest_turn, cur, targets);
            cerr << "init best_score2: " << best_score2 << endl;
            long cur_score2 = best_score2;

            int itr2 = 0, update_cnt2 = 0;
            while(!tk.is_time_over()) {
                int a = mt() % targets.size();
                int b = mt() % targets.size();
                if(a == b) continue;
                itr2++;

                swap(targets[a], targets[b]);
                long new_score2 = calc_score2(b, s, rest_turn, cur, targets);

                if(temp2.changed(cur_score2 - new_score2)) {
                    update_cnt2++;
                    cur_score2 = new_score2;
                    if(new_score2 > best_score2) {
                        best_score2 = new_score2;
                        // cerr << "new best_score2: " << best_score2 << endl;
                    }
                } else {
                    swap(targets[a], targets[b]);
                }
            }

            // cerr << "itr2: " << itr2 << " update_cnt2: " << update_cnt2 << " best_score2: " << best_score2 << endl;
        }

        REP(i, 0, targets.size()) {
            pint target = targets[i];
            move(cur, target, ans);
            if(ans.size() >= T) break;
            if(i == targets.size() - 1 && b < 19) {
                shelters.push_back(cur);
                shelters_map[cur.first][cur.second] = 1;
                copy(s, cur, ans);
                break;
            }
            write(s, cur, ans);
            board[target.first][target.second] = 1;
            rest--;
        }

        if(ans.size() >= T) break;
        /*
        REP(i, 0, N) {
            REP(j, 0, N) {
                cerr << bitset<20>(A[i][j]) << " ";
            }
            cerr << endl;
        }
        */
    }
    long final_score = 0;
    REP(i, 0, N) {
        REP(j, 0, N) {
            final_score += A[i][j];
        }
    }
    cerr << "final score: " << final_score << endl;

    if(ans.size() >= T) {
        ans = ans.substr(0, T);
    }
    for(char c: ans) {
        cout << c << endl;
    }
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    
    cin >> N >> T;
    A.resize(N, vi(N));
    REP(i, 0, N) {
        REP(j, 0, N) {
            cin >> A[i][j];
        }
    }
    solve();
}
0