费解的开关--算法竞赛进阶指南

你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

我们用数字“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

/*
1.一个格子最多只能变色一次,因为变色两次后会恢复原状,所以只能变色一次
2. 当第一行确定时,只能通过第二行去改变第一行状态,然后通过第三行改变第二行状态,以此类推 
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> 

using namespace std;

char map[5][6];
char tmpMap[5][6];

void turn(int x, int y)
{
	tmpMap[x][y]^=1;
	if(x > 0) tmpMap[x-1][y]^=1;
	if(x < 4) tmpMap[x+1][y]^=1;
	if(y < 4) tmpMap[x][y+1]^=1;
	if(y > 0) tmpMap[x][y-1]^=1;
}

int main()
{
	int n;
	cin >> n;
	while(n--)
	{
		//获取数据 
		for(int i = 0; i < 5; i++) cin >> map[i];
		//枚举第一行的所有状态 
		int count = 7;
		for(int i = 0; i < 32; i++)
		{
			int tmpCount = 0;
			memcpy(tmpMap, map, sizeof(char)*30);
			//第一行状态变化 
			for(int j = 0; j < 5; j++)
			{
				if(i >> j & 1){
					turn(0, j);
					tmpCount++;
				}
			}
			//转变第二行以及后面几行状态 
			for(int j = 1; j < 5; j++)
			{
				for(int k = 0; k < 5; k++)
				{
					//如果上一行有没变成1的,这一行这一列变化,影响上一行,导致其变成1 
					if(tmpMap[j-1][k] == '0')
					{
						turn(j, k);
						tmpCount++;
					}
				}
			}
			
			bool check = true;
			for(int j = 0; j < 5; j++)
			{
				//对最后一行进行判断 
				if(tmpMap[4][j] == '0')
				{
					check = false;
				}
			}
			if(check) count = min(tmpCount, count); 
		} 
		if(count <= 6) printf("%d\n", count);
		else printf("%d\n",-1);
	}
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章