Acwing95 费解的开关(状压搜索)

题目

简要概括一下题目:有一个5乘5的01矩阵,通过变换让其中元素全变成1,求最小变换的次数。

这里的变换是指一个元素本身和他的上下左右共五个元素异或1。

思路:首先对第一排确定一种变换方案,将第一排固定,如果为该位置是0,通过变换第二排的该位置元素使他变成1即可,依次向下求得最优方案。

枚举第一排的变换方案,每一个位置可选择变或不变,则考虑用状态压缩,枚举0到31这32个数(2的5次方),二进制下1表示变,0不变。

#include <bits/stdc++.h>
using namespace std;
int dx[5] = {-1, 0, 1, 0, 0};
int dy[5] = {0, 1, 0, -1, 0};
int a[6][6], b[6][6], ans, ans1;
void cal(int x, int y) {//变换操作
	for (int i = 0; i < 5; i ++) {
		int x1 = x + dx[i], y1 = y + dy[i];
		if (x1 >= 1 && x1 <= 5 && y1 >= 1 && y1 <= 5)
			b[x1][y1] ^= 1;
	}
}
void dfs(int x) {//搜索
	if (x > 5) return ;
	for (int i = 1; i <= 5; i ++) {
		if (b[x - 1][i] == 0) cal(x, i), ans ++;
		else continue;
	}
	dfs(x + 1);
}
int main() {
	int n; cin >> n;
	while (n --) {
		ans1 = 0x3f3f3f3f;
		for (int i = 1; i <= 5; i ++) {
			for (int j = 1; j <= 5; j ++) {
				char str; cin >> str;
				if (str == '0') a[i][j] = 0;
				else a[i][j] = 1;
			}
		}
		for (int bit = 0; bit <= 31; bit ++) {//状态压缩枚举第一排 
			ans = 0;
			int res = 0, f = 0;
			memcpy(b, a, sizeof(b));
			int cnt = bit;
			for (; cnt; cnt >>= 1) {//位运算,取出每一位 
				res ++;
				if (cnt & 1) cal(1, res), ans ++;//处理第一排 
			}
			dfs(2);//从第二排依次向下处理 
			for (int m = 1; m <= 5; m ++)
				if (b[5][m] == 0) {//无解 
					f = 1;
					break;
				}
			if (f == 1) continue ;
			ans1 = min(ans1, ans);
		}
		if (ans1 > 6) cout << -1 << endl;
		else cout << ans1 << endl;
	}
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值