結果

問題 No.5022 XOR Printer
ユーザー ぬるぽ
提出日時 2025-07-26 15:17:53
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 1,563 ms / 2,000 ms
コード長 9,282 bytes
コンパイル時間 4,256 ms
コンパイル使用メモリ 307,920 KB
実行使用メモリ 7,716 KB
スコア 5,083,346,097
最終ジャッジ日時 2025-07-26 15:19:01
合計ジャッジ時間 67,748 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 50
権限があれば一括ダウンロードができます

ソースコード

diff #

//  greedy_xor_v12.cpp
//  ------------------------------------------------------------------
//  • 80 万台 / 90 万台セルを 2 マスずつ残す制約は維持
//  • **a 候補を 2 つ選び,現在位置から近い方** を採用
//      1. まず “残数 > reserve” を満たす 80/90 万台セルを
//         値が小さい順に最大 2 個収集(high 候補)
//      2. 足りなければその他セルから値が小さい順に追加して計 2 個に
//      3. その 2 個のうち,Manhattan 距離が短い方を a とする
//  • stderr には各ステップ詳細 + 最終スコア + 総ステップ数
//  • stdout は提出用操作列(1 行 1 文字)
//  ------------------------------------------------------------------

#include <bits/stdc++.h>
using namespace std;

constexpr int MAX_COST12 = 30;
constexpr int MAX_COST3  = 45;
constexpr int LOW80 = 800000, HIGH80 = 899999;
constexpr int LOW90 = 900000, HIGH90 = 999999;

struct Plan{
    double ratio=-1; int gain=0,cost=0; char type=0;
    int ar=0,ac=0,b1r=0,b1c=0,b2r=0,b2c=0,b3r=0,b3c=0;
};
inline int manh(int r1,int c1,int r2,int c2){ return abs(r1-r2)+abs(c1-c2); }
void addMoves(int r1,int c1,int r2,int c2,vector<char>& ops){
    if(r2>r1) ops.insert(ops.end(),r2-r1,'D'); else ops.insert(ops.end(),r1-r2,'U');
    if(c2>c1) ops.insert(ops.end(),c2-c1,'R'); else ops.insert(ops.end(),c1-c2,'L');
}
bool in80(int v){ return LOW80<=v && v<=HIGH80; }
bool in90(int v){ return LOW90<=v && v<=HIGH90; }

int main(){
    ios::sync_with_stdio(false); cin.tie(nullptr);

    int N,T; if(!(cin>>N>>T)) return 0;
    vector<vector<int>> A(N,vector<int>(N));
    for(auto& row:A) for(int& x:row) cin>>x;

    vector<pair<int,int>> cells;
    cells.reserve(N*N);
    for(int i=0;i<N;i++) for(int j=0;j<N;j++) cells.emplace_back(i,j);

    int init80=0, init90=0;
    for(auto [i,j]:cells){
        int v=A[i][j];
        if(in80(v)) ++init80;
        else if(in90(v)) ++init90;
    }
    const int reserve80 = (init80>=2 ? 2 : 0);
    const int reserve90 = (init90>=2 ? 2 : 0);
    int remain80 = init80, remain90 = init90;

    vector<vector<char>> blocked(N,vector<char>(N,0));

    int r=0,c=0,s=0;
    vector<char> ops;
    int step=1;

    auto skip_by_reserve=[&](int v){ return (in80(v)&&remain80<=reserve80)||(in90(v)&&remain90<=reserve90); };

    while(true){
        // ---------- a 候補 2 つを選ぶ ----------
        vector<pair<int,int>> high, rest;
        for(auto [i,j]:cells){
            if(blocked[i][j]) continue;
            int v=A[i][j];
            bool highFlag = (in80(v)&&remain80>reserve80) || (in90(v)&&remain90>reserve90);
            if(highFlag) high.emplace_back(i,j);
            else         rest.emplace_back(i,j);
        }
        auto by_val=[&](auto p1,auto p2){ return A[p1.first][p1.second] < A[p2.first][p2.second]; };
        std::sort(high.begin(),high.end(),by_val);
        std::sort(rest.begin(),rest.end(),by_val);

        vector<pair<int,int>> cand;
        for(auto p:high){
            cand.push_back(p);
            if((int)cand.size()==2) break;
        }
        for(auto p:rest){
            cand.push_back(p);
            if((int)cand.size()==2) break;
        }
        if(cand.empty()) break;                 // 全ブロック済み

        // 近い方を a に
        int ar=cand[0].first, ac=cand[0].second;
        if(cand.size()==2){
            int d0=manh(r,c, cand[0].first,cand[0].second);
            int d1=manh(r,c, cand[1].first,cand[1].second);
            if(d1<d0) { ar=cand[1].first; ac=cand[1].second; }
        }

        int a_val=A[ar][ac];
        Plan best; best.ar=ar; best.ac=ac;

        // ---------- 1‑copy ----------
        for(auto [br,bc]:cells){
            if(br==ar&&bc==ac) continue;
            if(skip_by_reserve(A[br][bc])) continue;
            int cost=manh(r,c,br,bc)+1+manh(br,bc,ar,ac)+1;
            if(cost>MAX_COST12||(int)ops.size()+cost>T) continue;
            int gain=(a_val^(s^A[br][bc]))-a_val;
            if(gain<=0) continue;
            double ratio=(double)gain/cost;
            if(ratio>best.ratio) best={ratio,gain,cost,'1',ar,ac,br,bc};
        }
        // ---------- 2‑copy ----------
        for(auto [b1r,b1c]:cells){
            if(b1r==ar&&b1c==ac) continue;
            if(skip_by_reserve(A[b1r][b1c])) continue;
            for(auto [b2r,b2c]:cells){
                if((b2r==ar&&b2c==ac)||(b2r==b1r&&b2c==b1c)) continue;
                if(skip_by_reserve(A[b2r][b2c])) continue;
                int cost=manh(r,c,b1r,b1c)+1+manh(b1r,b1c,b2r,b2c)+1+manh(b2r,b2c,ar,ac)+1;
                if(cost>MAX_COST12||(int)ops.size()+cost>T) continue;
                int gain=(a_val^(s^A[b1r][b1c]^A[b2r][b2c]))-a_val;
                if(gain<=0) continue;
                double ratio=(double)gain/cost;
                if(ratio>best.ratio) best={ratio,gain,cost,'2',ar,ac,b1r,b1c,b2r,b2c};
            }
        }
        // ---------- 3‑copy ----------
        for(auto [b1r,b1c]:cells){
            if(b1r==ar&&b1c==ac) continue;
            if(skip_by_reserve(A[b1r][b1c])) continue;
            for(auto [b2r,b2c]:cells){
                if((b2r==ar&&b2c==ac)||(b2r==b1r&&b2c==b1c)) continue;
                if(skip_by_reserve(A[b2r][b2c])) continue;
                for(auto [b3r,b3c]:cells){
                    if(b3r==ar&&b3c==ac) continue;
                    if((b3r==b1r&&b3c==b1c)||(b3r==b2r&&b3c==b2c)) continue;
                    if(skip_by_reserve(A[b3r][b3c])) continue;
                    int cost=manh(r,c,b1r,b1c)+1+manh(b1r,b1c,b2r,b2c)+1+
                             manh(b2r,b2c,b3r,b3c)+1+manh(b3r,b3c,ar,ac)+1;
                    if(cost>MAX_COST3||(int)ops.size()+cost>T) continue;
                    int gain=(a_val^(s^A[b1r][b1c]^A[b2r][b2c]^A[b3r][b3c]))-a_val;
                    if(gain<=0) continue;
                    double ratio=(double)gain/cost;
                    if(ratio>best.ratio) best={ratio,gain,cost,'3',ar,ac,b1r,b1c,b2r,b2c,b3r,b3c};
                }
            }
        }

        // ---------- 改善手なし → ブロック ----------
        if(best.ratio<0){
            blocked[ar][ac]=1;
            continue;
        }

        // ---------- ログ ----------
        cerr<<"Step "<<step<<": "<<best.type<<"-copy "
            <<"a=("<<best.ar+1<<","<<best.ac+1<<") val="<<a_val;
        if(best.type=='1'){
            cerr<<" | b=("<<best.b1r+1<<","<<best.b1c+1<<") val="<<A[best.b1r][best.b1c];
        }else if(best.type=='2'){
            cerr<<" | b1=("<<best.b1r+1<<","<<best.b1c+1<<") val="<<A[best.b1r][best.b1c]
                <<" | b2=("<<best.b2r+1<<","<<best.b2c+1<<") val="<<A[best.b2r][best.b2c];
        }else{
            cerr<<" | b1=("<<best.b1r+1<<","<<best.b1c+1<<") val="<<A[best.b1r][best.b1c]
                <<" | b2=("<<best.b2r+1<<","<<best.b2c+1<<") val="<<A[best.b2r][best.b2c]
                <<" | b3=("<<best.b3r+1<<","<<best.b3c+1<<") val="<<A[best.b3r][best.b3c];
        }
        cerr<<" | s="<<s<<" | gain="<<best.gain<<"/cost="<<best.cost<<"\n";

        // ---------- 残数更新 ----------
        if(in80(a_val)) --remain80;
        else if(in90(a_val)) --remain90;
        auto after_write=[&](int oldv,int newv){
            if(in80(oldv)&&!in80(newv)) --remain80;
            else if(!in80(oldv)&&in80(newv)) ++remain80;
            if(in90(oldv)&&!in90(newv)) --remain90;
            else if(!in90(oldv)&&in90(newv)) ++remain90;
        };

        // ---------- 実行 ----------
        if(best.type=='1'){
            int vb=A[best.b1r][best.b1c];
            addMoves(r,c,best.b1r,best.b1c,ops); ops.push_back('C');
            s^=vb; r=best.b1r; c=best.b1c;
            addMoves(r,c,ar,ac,ops); ops.push_back('W');
            int old=A[ar][ac]; A[ar][ac]^=s; after_write(old,A[ar][ac]);
            r=ar; c=ac;
        }else if(best.type=='2'){
            int vb1=A[best.b1r][best.b1c], vb2=A[best.b2r][best.b2c];
            addMoves(r,c,best.b1r,best.b1c,ops); ops.push_back('C');
            s^=vb1; r=best.b1r; c=best.b1c;
            addMoves(r,c,best.b2r,best.b2c,ops); ops.push_back('C');
            s^=vb2; r=best.b2r; c=best.b2c;
            addMoves(r,c,ar,ac,ops); ops.push_back('W');
            int old=A[ar][ac]; A[ar][ac]^=s; after_write(old,A[ar][ac]);
            r=ar; c=ac;
        }else{
            int vb1=A[best.b1r][best.b1c], vb2=A[best.b2r][best.b2c], vb3=A[best.b3r][best.b3c];
            addMoves(r,c,best.b1r,best.b1c,ops); ops.push_back('C');
            s^=vb1; r=best.b1r; c=best.b1c;
            addMoves(r,c,best.b2r,best.b2c,ops); ops.push_back('C');
            s^=vb2; r=best.b2r; c=best.b2c;
            addMoves(r,c,best.b3r,best.b3c,ops); ops.push_back('C');
            s^=vb3; r=best.b3r; c=best.b3c;
            addMoves(r,c,ar,ac,ops); ops.push_back('W');
            int old=A[ar][ac]; A[ar][ac]^=s; after_write(old,A[ar][ac]);
            r=ar; c=ac;
        }
        ++step;
    }

    // ---------- 終了ログ ----------
    long long total=0;
    for(auto& row:A) for(int v:row) total+=v;
    cerr<<"Final score: "<<total<<"\n";
    cerr<<"Total steps: "<<step-1<<"\n";

    // ---------- 出力 ----------
    for(char ch:ops) cout<<ch<<'\n';
    return 0;
}
0