• 费解的开关


    Q

    你玩过“拉灯”游戏吗?
    
    25 盏灯排成一个 5×5 的方形。
    
    每一个灯都有一个开关,游戏者可以改变它的状态。
    
    每一步,游戏者可以改变某一个灯的状态。
    
    游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
    
    我们用数字 1 表示一盏开着的灯,用数字 0 表示关着的灯。
    
    下面这种状态
    
    10111
    01101
    10111
    10000
    11011
    在改变了最左上角的灯的状态后将变成:
    
    01111
    11101
    10111
    10000
    11011
    再改变它正中间的灯后状态将变成:
    
    01111
    11001
    11001
    10100
    11011
    给定一些游戏的初始状态,编写程序判断游戏者是否可能在 6 步以内使所有的灯都变亮。
    
    输入格式
    第一行输入正整数 n,代表数据中共有 n 个待解决的游戏初始状态。
    
    以下若干行数据分为 n 组,每组数据有 5 行,每行 5 个字符。
    
    每组数据描述了一个游戏的初始状态。
    
    各组数据间用一个空行分隔。
    
    输出格式
    一共输出 n 行数据,每行有一个小于等于 6 的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。
    
    对于某一个游戏初始状态,若 6 步以内无法使所有灯变亮,则输出 −1。
    
    数据范围
    0<n≤500
    输入样例:
    3
    00111
    01011
    10001
    11010
    11100
    
    11101
    11101
    11110
    11111
    11111
    
    01111
    11111
    11111
    11111
    11111
    输出样例:
    
    3
    2
    -1
    

    A

    #include<iostream>
    #include<cstring>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    char g[10][10];
    int dx[5] = {0, -1, 0, 1, 0}, dy[5] = {0, 0, 1, 0, -1}; //origin,left,down,right,up
    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;//48 二进制: 110000 ,和1 异或得到 110001)得到的是49,正好是49,对应的字符是’1’.
    		}
    	}
    }
    int work () {
    	int ans = INF;
    	for (int k = 0; k < 1 << 5; ++k) {
    		int res = 0;
    		char backup[10][10];
    		memcpy(backup, g, sizeof(g));
    		for (int j = 0; j < 5; ++j) {
    			if (k >> j & 1) {
    				++res;
    				turn(0, j);
    			}
    		}
    		for (int i = 0; i < 4; ++i) {
    			for (int j = 0; j < 5; ++j) {
    				if ('0' == g[i][j]) {
    					++res;
    					turn(i + 1, j);
    				}
    			}
    		}
    		bool is_successful = true;
    		for (int i = 0; i < 5; ++i) {
    			if ('0' == g[4][i]) {
    				is_successful = false;
    				break;
    			}
    		}
    		if (is_successful) {
    			ans = min(ans, res);
    		}
    		memcpy(g, backup, sizeof backup);
    		
    		
    	}
    	if (ans > 6) {
    		ans = -1;
    	}
    	return ans;
    }
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	int T;
    	cin >> T;
    	while (T--) {
    		for (int i = 0; i < 5; ++i) {
    			cin >> g[i];
    		}
    		cout << work() << '\n';
    	}
    	return 0;
    }
    
  • 相关阅读:
    mysql逻辑备份
    Configuring ProxySQL
    CSS伸缩布局
    溢出文字隐藏三种方式
    CSS过渡效果transition和动画
    伪元素before和after本质
    css滑动门技术
    字体图标iconfont
    CSS精灵技术(sprite)
    行内块和文字垂直对齐vertical-agign
  • 原文地址:https://www.cnblogs.com/jeseesmith/p/15988801.html
Copyright © 2020-2023  润新知