【AcWing】费解的开关

题目:
AcWing 费解的开关
在这里插入图片描述

思想:

  • 只能从下一行去改变上一行的状态,因此第一行的状态即全局状态
  • 对第一行,存在00000~11111共2^5=32种turn的方案,这32种方案会导致我们对输入的原始第一行数据进行32种不同的开关灯操作,某位上为1则对原始数据第一行该位上进行turn操作。随后对第一行每一种方案再进行枚举
  • 对5×5的前4行的每一行,若某个元素为‘0’,则下一行的该位置需要按一下(turn)。
  • 检查到最后一行,若最后一行全都为1,则可以使灯全亮
  • 若某方案的turn操作次数大于6,则不符合题意。
  • 每个方案尝试结束后,还原原始数据g数组
#include <iostream>
#include <cstring>
using namespace std;
const int INF=1000000;
char g[10][10];
int dx[5]={0,-1,0,1,0},dy[5]={0,0,1,0,-1};
//向量表示:dx表示行变化,中0上-1右0下+1左0
//y表示列变化,中0上0右+1下0左-1
void turn(int x,int y){ //对某灯包括其周围4个方向的灯进行开关
	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){ //保证在5×5范围内进行turn
			g[a][b]^=1; //'0'==48,偶数异或1为偶数+1。'1'==49,奇数异或1为奇数-1。实现开关。
		}
	}
}
int work(){
	int ans=INF; //Infinity 无穷大
	for(int k=0;k<1<<5;k++){ //枚举00000~11111,2^5种方案
		int res=0;
		char backup[10][10];//备份g数组
		memcpy(backup,g,sizeof g);//cstring库,一般用于字符数组复制。void* void* size_t(要复制的字节数)
		for(int j=0;j<5;j++){
			if(k >> j & 1){
			    res++; //操作次数+1
				turn(0,j); //对第一行进行turn操作,32种turn方案逐次尝试
			}
		}
		for(int i=0;i<4;i++){
			for(int j=0;j<5;j++){
				if(g[i][j]=='0'){
					res++; 
					turn(i+1,j);//对下一行对应位置turn,使得当前行被点亮
				}
			}
		}
		bool flag=true;
		for(int j=0;j<5;j++){
			if(g[4][j]=='0'){ //最后一行并非全'1'
				flag=false;
				break;
			}
		}
		if(flag) ans=min(ans,res);
		memcpy(g,backup,sizeof backup); //还原原始数据,尝试下一种第一行turn方案
	}
	if(ans>6) ans=-1;
	return ans;
}

int main(){
	int n;
	cin >> n;
	while(n--){
		for(int i=0;i<5;i++){
			cin >> g[i];
		}
		cout << work() << endl;
	}
	return 0;
}

END

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值