专栏文章

题解:AT_abc424_d [ABC424D] 2x2 Erasing 2

AT_abc424_d题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minsf7r1
此快照首次捕获于
2025/12/02 07:35
3 个月前
此快照最后确认于
2025/12/02 07:35
3 个月前
查看原文

题意

给定一个矩阵,每个格子为白色或黑色。每次我们可以使一个黑色格子变为白色,求使得矩阵中没有 2×22×2 的黑色子矩阵的最小操作数。

做法

注意到 hhww 最大为 77,考虑状压 DPDP
f[s][i]f[s][i] 表示当前走到了第 ii 行,当前行状态为 ss 且满足在此行前不存在 2×22 × 2 的黑色子矩阵的最小操作次数。
可以存储每一行的初始状态 sitsit,预处理出每一行的合法状态 ss,计算 sitsitss 的黑格变化个数。
用上一行的状态来更新这一行的答案,按位比对判断两行状态是否满足不存在 2×22 × 2 黑色子矩阵。
复杂度 O(Twh2w)O(Twh2^w)

代码

CPP
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
int T,h,w;
string s;
int sit[10],f[(1<<10)][10];
vector<pair<int,int> > e[10];
int sum(int x,int p){
	cerr<<x<<" "<<p<<")))\n";
	int sum = 0;
	for(int i=0;i<w;i++){
		if(!((x >> i) & 1) && !((p >> i) & 1)) sum++;
	}
	cerr<<sum<<"???\n";
	return sum;
}
bool check(int x,int y){
	for(int i=0;i<w;i++){
		if(((x >> i) & 3) == 3 && ((y >> i) & 3) == 3) return false;
	}
	return true;
}
void solve(){
	cin >> h >> w;
	for(int i=1;i<=h;i++){
		cin >> s;
		for(int j=0;j<s.size();j++){
			if(s[j]=='.') sit[i] += (1 << j);
		}
	}
	for(int i=1;i<=h;i++){
		for(int p=0;p<(1<<w);p++){
			f[p][i] = INT_MAX;
			if(!(sit[i] & p)) e[i].push_back({p,sum(sit[i],p)});
		}
	}
	for(auto x : e[1]){
		f[x.fi][1] = x.se;
	}
	for(int i=2;i<=h;i++){
		for(auto x : e[i]){
			for(auto y : e[i - 1]){
				if(check(x.fi,y.fi)){
					f[x.fi][i] = min(f[x.fi][i],f[y.fi][i-1] + x.se);
				}
			}
		}
	}
	int ans = INT_MAX;
	for(auto x : e[h]){
		ans = min(ans,f[x.fi][h]);
	}
	cout << ans << "\n";
	memset(sit,0,sizeof sit);
	for(int i=1;i<=9;i++){
		e[i].clear();
	}
}
int main(){
	cin >> T;
	while(T--){
		solve();
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...