費解的開關--算法競賽進階指南

你玩過“拉燈”遊戲嗎?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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章