Submission #69491086
Source Code Expand
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
using ll = long long;
int solve_one(int H, int W, const vector<string>& S) {
// 黒マスに番号を割り当てる
map<pair<int,int>, int> id;
int idx = 0;
for(int i=0; i<H; i++){
for(int j=0; j<W; j++){
if(S[i][j] == '#'){
id[{i,j}] = idx++;
}
}
}
int M = idx; // 黒マスの総数
// 2x2 黒ブロックを列挙 bitmaskで高速化
// 黒マスは 最大49個?->uint64_t
vector<uint64_t> blocks;
for(int i=0; i+1<H; i++){
for(int j=0; j+1<W; j++){
if(S[i][j]=='#' && S[i][j+1]=='#' && S[i+1][j]=='#' && S[i+1][j+1]=='#'){
uint64_t mask=0;
mask |= 1ULL<<id[{i,j}];
mask |= 1ULL<<id[{i,j+1}];
mask |= 1ULL<<id[{i+1,j}];
mask |= 1ULL<<id[{i+1,j+1}];
blocks.push_back(mask);
}
}
}
if(blocks.empty()) return 0; // もともとOK
int best = M; // 最悪は黒マス全部塗り替え
// dfsで全パターン探索
// bi:今処理しているブロック(2×2)の番号
// used:これまでに白にしたマスの数
function<void(int,uint64_t,int)> dfs = [&](int bi, uint64_t removed, int used){
if(used >= best) return; // 剪定
// used 個マスを白にした状態 -> 残り R 個のブロックが壊れていない
// 奇跡的に「1 つのマスで 4 ブロック壊せる」状況が最大限続いたとしても
// 最低でも ceil(R/4) 個は追加で塗らないと絶対壊せない
// 今後どう頑張っても あと ceil(R/4) 個は絶対必要 -> used + ceil(R/4) 個以上
// どうやってもこれ以上は改善できない -> 剪定
int remaining=0;
for(int k=bi; k<(int)blocks.size(); k++){
if((blocks[k] & removed)==0) remaining++;
}
int lower=(remaining+3)/4;
if(used+lower>=best) return;
// すべて壊れてるならbest更新
if(bi == (int)blocks.size()){
best = min(best, used);
return;
}
// このブロックがすでに壊れているなら次のブロックへ
if(blocks[bi] & removed){
dfs(bi+1, removed, used);
return;
}
// 壊れていないなら、このブロックのどれかを白にする
uint64_t mask=blocks[bi];
for(int k=0; k<M; k++){
if(mask>>k & 1ULL){
dfs(bi+1,removed|(1ULL<<k),used+1);
}
}
};
dfs(0,0,0);
return best;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T; cin >> T;
while(T--){
int H, W; cin >> H >> W;
vector<string> S(H);
for(int i=0; i<H; i++) cin >> S[i];
cout << solve_one(H,W,S) << "\n";
}
return 0;
}
Submission Info
Submission Time |
|
Task |
D - 2x2 Erasing 2 |
User |
tkar821 |
Language |
C++ 23 (gcc 12.2) |
Score |
425 |
Code Size |
3054 Byte |
Status |
AC |
Exec Time |
20 ms |
Memory |
3696 KiB |
Judge Result
Set Name |
Sample |
All |
Score / Max Score |
0 / 0 |
425 / 425 |
Status |
|
|
Set Name |
Test Cases |
Sample |
example_00.txt |
All |
example_00.txt, hand_00.txt, hand_01.txt, hand_02.txt, hand_03.txt, hand_04.txt, hand_05.txt, random_00.txt, random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt, random_18.txt, random_19.txt |
Case Name |
Status |
Exec Time |
Memory |
example_00.txt |
AC |
1 ms |
3496 KiB |
hand_00.txt |
AC |
7 ms |
3560 KiB |
hand_01.txt |
AC |
1 ms |
3560 KiB |
hand_02.txt |
AC |
1 ms |
3564 KiB |
hand_03.txt |
AC |
1 ms |
3484 KiB |
hand_04.txt |
AC |
20 ms |
3640 KiB |
hand_05.txt |
AC |
1 ms |
3452 KiB |
random_00.txt |
AC |
1 ms |
3464 KiB |
random_01.txt |
AC |
1 ms |
3568 KiB |
random_02.txt |
AC |
1 ms |
3488 KiB |
random_03.txt |
AC |
1 ms |
3440 KiB |
random_04.txt |
AC |
1 ms |
3568 KiB |
random_05.txt |
AC |
1 ms |
3572 KiB |
random_06.txt |
AC |
4 ms |
3640 KiB |
random_07.txt |
AC |
5 ms |
3460 KiB |
random_08.txt |
AC |
3 ms |
3488 KiB |
random_09.txt |
AC |
4 ms |
3556 KiB |
random_10.txt |
AC |
3 ms |
3696 KiB |
random_11.txt |
AC |
14 ms |
3436 KiB |
random_12.txt |
AC |
16 ms |
3464 KiB |
random_13.txt |
AC |
18 ms |
3508 KiB |
random_14.txt |
AC |
17 ms |
3468 KiB |
random_15.txt |
AC |
3 ms |
3496 KiB |
random_16.txt |
AC |
15 ms |
3640 KiB |
random_17.txt |
AC |
13 ms |
3496 KiB |
random_18.txt |
AC |
15 ms |
3572 KiB |
random_19.txt |
AC |
17 ms |
3504 KiB |