• 《算法竞赛进阶指南》 第一章 Acwing 95. 费解的开关


    地址 https://www.acwing.com/problem/content/97/

    你玩过“拉灯”游戏吗?
    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
    

    解答
    由游戏规则可知 每点可以至多一次(点击两次恢复原状) 点击ABC CBA BAC等操作次序不影响最后达到的状态
    思路如下 第一行有5个点 每个点的状态非0即1 那么就是2^5个状态集合
    以这些第一行的状态为起点 逐步递推出下一行如何操作

    如图 第一行状态确定后 无论第二行状态如何 我们必须点击第二行蓝色点才能使得第一行全部为1
    而想使得第二行完全为1 则需要点击第三行 如果递推
    最后推断到最后一行 可知是否有解。

    #include <iostream>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    int n;
    int ans;
    string gra[5];
    
    int addx[5] = { 1,-1,0,0,0 };
    int addy[5] = { 0,0,0,-1,1 };
    
    
    void click(int g[5][5], int x, int y) {
    	for (int i = 0; i < 5; i++) {
    		int newx = x + addx[i];
    		int newy = y + addy[i];
    
    		if (newx >= 0 && newx < 5 && newy >= 0 && newy < 5) {
    			g[newx][newy] ^= 1;
    		}
    	}
    }
    
    
    void solve()
    {
    	ans = -1;
    	for (int i = 0; i < 1 << 5; i++) {
    		int currClick = 0;
    		int tmp[5][5];
    		for (int i = 0; i < 5; i++) {
    			for (int j = 0; j < 5; j++) {
    				tmp[i][j] = gra[i][j] - '0';
    			}
    		}
    
    		for (int k = 0; k < 5; k++) {
    			if (i & (1 << k)) {
    				click(tmp, 0, k);
    				currClick++;
    			}
    		}
    
    		//第一排确认以后 递推后面的点击位置
    		for (int k = 0; k < 4; k++) {
    			for (int j = 0; j < 5; j++) {
    				if (tmp[k][j] != 1) {click(tmp, k + 1, j); currClick++;}
    			}
    		}
    
    		if (currClick > 6) continue;
    
    		//检查最后一排是否为全1
    		for (int i = 0; i < 5; i++) {
    			if (tmp[4][i] == 0) { currClick = -1; break; }
    		}
    
    		if (currClick != -1 && (-1 == ans || currClick < ans)) {ans = currClick;}
    	}
    }
    
    
    int main() {
    	cin >> n;
    
    	while (n--) {
    		for (int i = 0; i < 5; i++) {
    			cin >> gra[i];
    		}
    		solve();
    		cout << ans << endl;
    	}
    
    	return 0;
    }
    

    我的视频题解空间

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    管理Linux软件——aptitude
    管理Linux软件——apt
    /etc/apt/sources.list 和 /etc/apt/sources.list.d
    JSR303参数校验正则表达式的莫名其妙的错误
    HighCharts 动态设置 series
    template might not exist or might not be accessible by any of the configured Template Resolvers
    springboot 热部署替代方式
    如果访问国外站点慢的话,可以多切换一下运营商,比如开热点。
    当 springboot 部署war包,tomcat报一堆无法解决的问题时
    thymeleaf在开发环境正常,但用jar运行时报错 Error resolving template template might not exist or might not be accessible
  • 原文地址:https://www.cnblogs.com/itdef/p/14631767.html
Copyright © 2020-2023  润新知