0
点赞
收藏
分享

微信扫一扫

【acwing】95. 费解的开关**(模拟|递推|二进制)

爱做梦的夏夏 2022-04-05 阅读 38
c++模拟

穿越隧道
在这里插入图片描述

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 510, M = 10;

char g[M][M],backup[M][M];
int dx[5] = {-1,0,1,0,0};
int dy[5] = {0,1,0,-1,0}; 
int n;
void turn(int x, int y){
	for(int i = 0; i < 5; i++){
		int a = x + dx[i], b = y + dy[i];
		if(a >= 0 && a < 5 && b >= 0 && b < 5){
			g[a][b] ^= 1;
			/*
			因为字符0和字符1,字符0为48,字符1为49(ASCII)。
			所以通过异或最后一位达到字符1和0的转化。 
			*/
		} 
	}
}
int main(){
	scanf("%d",&n);
	while(n--){
		for(int i = 0; i < 5; i++) scanf("%s",g[i]);
		int res = 10;
		for(int op = 0; op < 32; op++){//枚举第一行所有的按法 2^5 = 32次,因题目要找最优解。 
			memcpy(backup,g,sizeof(g));
			int step = 0;
			/*处理第一行:
			1.此处1表示按,0表示不按。
			为下面行做准备 
			*/
			for(int i = 0; i < 5; i++){//第一行中的每一个元素 
				if(op >> i & 1){//op为第一行按灯开关的32种方式。某一种方式的二进制的哪几位为1,则进行turn操作 
					step++;
					turn(0,i); 
				} 
			}
			for(int i = 0; i < 4; i++){
				for(int j = 0; j < 5; j++){
					if(g[i][j] == '0'){
						step++;
						turn(i+1,j);//第i行固定了,只能通过i+1行来改变第i行的状态。 
					}
				}
			}
			/*遍历最后一行的每一个元素,看这个方案下,是否能使最后一行灯全亮*/ 
			bool succ = true;
			for(int i = 0; i < 5; i++){
				if(g[4][i] == '0'){
					succ = false;
					break;	
				} 
			} 
			if(succ) res = min(res,step);
			memcpy(g,backup, sizeof(g));//将原始数组赋给g. 
		}
		if(res > 6) puts("-1");
		else printf("%d\n",res); 
	}
	return 0;	
}
举报

相关推荐

0 条评论