結果
問題 |
No.5022 XOR Printer
|
ユーザー |
![]() |
提出日時 | 2025-07-26 14:42:20 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,168 ms / 2,000 ms |
コード長 | 8,395 bytes |
コンパイル時間 | 3,646 ms |
コンパイル使用メモリ | 298,576 KB |
実行使用メモリ | 7,716 KB |
スコア | 5,074,959,413 |
最終ジャッジ日時 | 2025-07-26 14:43:19 |
合計ジャッジ時間 | 54,636 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
ソースコード
// greedy_xor_v10.cpp // ------------------------------------------------------------------ // ポイント // * 800 000‑899 999 を “80 万台”, // 900 000‑999 999 を “90 万台” と定義。 // * それぞれ **最終的に 2 マスは残す** という制約を追加。 // ‑ 初期状態でそのレンジに 2 未満しか無ければ制約なし。 // ‑ 残数 (= まだレンジ内にあるマス数) が reserve(=2) 以下に // なったら、そのレンジのセルは以後スキップ(改善対象にしない)。 // * 改善手ゼロなら “ブロック” は従来通り。 // * その他手数・コピー 1/2/3 評価ロジックは v9 と同じ。 // ------------------------------------------------------------------ #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'); } 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(LOW80<=v && v<=HIGH80) ++init80; else if(LOW90<=v && v<=HIGH90) ++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 in80=[&](int v){return LOW80<=v && v<=HIGH80;}; auto in90=[&](int v){return LOW90<=v && v<=HIGH90;}; while(true){ // ----- choose a ----- int ar=-1,ac=-1,min_val=INT_MAX; // phase 1: 80/90 万レンジ優先(残数 > reserve) auto try_pick=[&](int low,int high,int remain,int reserve)->bool{ bool found=false; for(auto [i,j]:cells){ if(blocked[i][j]) continue; int v=A[i][j]; if(v<low||v>high) continue; if(remain<=reserve) continue; // 残すべき数を下回るので不可 if(v<min_val){ min_val=v; ar=i; ac=j; found=true;} } return found; }; bool picked = try_pick(LOW80,HIGH80,remain80,reserve80) || try_pick(LOW90,HIGH90,remain90,reserve90); // phase 2: 全体最小値 if(!picked){ for(auto [i,j]:cells){ if(blocked[i][j]) continue; int v=A[i][j]; if(v<min_val){ min_val=v; ar=i; ac=j; picked=true; } } } if(!picked) break; // 全ブロック済み int a_val=A[ar][ac]; Plan best; best.ar=ar; best.ac=ac; auto skip_by_reserve=[&](int i,int j)->bool{ int v=A[i][j]; if(in80(v) && remain80<=reserve80) return true; if(in90(v) && remain90<=reserve90) return true; return false; }; // ---------- 1‑copy ---------- for(auto [br,bc]:cells){ if(br==ar&&bc==ac) continue; if(skip_by_reserve(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(b1r,b1c)) continue; for(auto [b2r,b2c]:cells){ if((b2r==ar&&b2c==ac)||(b2r==b1r&&b2c==b1c)) continue; if(skip_by_reserve(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(b1r,b1c)) continue; for(auto [b2r,b2c]:cells){ if((b2r==ar&&b2c==ac)||(b2r==b1r&&b2c==b1c)) continue; if(skip_by_reserve(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(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}; } } } // --- 改善手無し → ブロックして continue --- if(best.ratio<0){ blocked[ar][ac]=1; continue; } // --- 残数更新 (a は必ず書き換わる) --- 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 oldA=A[ar][ac]; A[ar][ac]^=s; after_write(oldA,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 oldA=A[ar][ac]; A[ar][ac]^=s; after_write(oldA,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 oldA=A[ar][ac]; A[ar][ac]^=s; after_write(oldA,A[ar][ac]); r=ar; c=ac; } ++step; } for(char ch:ops) cout<<ch<<'\n'; return 0; }