费解的开关 递推

题目链接:AcWing 95. 费解的开关 - AcWing

        题意: 有5 排 5列一共25盏灯,每盏灯有开和关两种状态, 初始灯开与关的状态不确定。现在可以对每盏灯进行操作,改变这盏灯的状态,同时这盏灯上下左右的灯的状态也会随之发生改变。问是否有一个最少的操作次数,而且该操作次数不能大于6,使所有的灯都变为开的状态。

        分析: 可以想到的是对于每盏灯最多就操作一次,而且操作的顺序毫无影响。那么假设当前排已经操作完了,但是还有灭的灯,只能在下一排的同一个位置把他打开,所以一旦第一排要操作哪几个灯已经确定,剩下的排的操作都是固定的。因此第一排操作的状态一共有2^5种,只需要枚举这些状态,找出答案的最小值即可。

代码:

#include<bits/stdc++.h>
#define map unordered_map
#define all(a) a.begin(), a.end()
using namespace std;

typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, int> PLI;
const int N = 310 + 10;
const int mod = 99824353;

int n;
string s[5];
string ss[5];
int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0};

void turn(int tx, int ty){
	for(int i = 0; i < 5; i ++){
		int x = tx + dx[i], y = ty + dy[i];
		if(x < 0 || x >= 5 || y < 0 || y >= 5) continue;
		if(ss[x][y] == '1') ss[x][y] = '0';
		else ss[x][y] = '1';
	}
}

void solve(){
	cin>>n;
	while(n --){
		for(int i = 0; i < 5; i ++) cin>>s[i];
		int ans = 7;
		for(int i = 0; i < 32; i ++){
			int step = 0;
			for(int j = 0; j < 5; j ++) ss[j] = s[j];
			for(int j = 0; j < 5; j ++){
				if((i >> j) & 1){
					turn(0, j);
					step ++;
				}
			}
			for(int j = 1; j < 5; j ++){
				for(int k = 0; k < 5; k ++){
					if(ss[j - 1][k] == '0') {
						turn(j, k);
						step ++;
					}
				}
			}
			bool f = 0;
			for(int j = 0; j < 5; j ++){
				if(ss[4][j] == '0') f = 1;
			}
			if(f) continue;
			ans = min(ans, step);
		}
		if(ans > 6) ans = -1;
		cout<<ans<<endl;
	}
}

int main(){
	cin.tie(0) -> sync_with_stdio(false);
	//int t; cin>>t; while(t --) 
		solve();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值