1. 程式人生 > >tyvj P1266 費解的開關

tyvj P1266 費解的開關

題目:

描述

    你玩過“拉燈”遊戲嗎?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個字元。每組資料描述了一個遊戲的初始狀態。各組資料間用一個空行分隔。
    對於30%的資料,n<=5;
    對於100%的資料,n<=500。

輸出格式

    輸出資料一共有n行,每行有一個小於等於6的整數,它表示對於輸入資料中對應的遊戲狀態最少需要幾步才能使所有燈變亮。
    對於某一個遊戲初始狀態,若6步以內無法使所有燈變亮,請輸出“-1”。

測試樣例1

輸入


00111 
01011 
10001 
11010 
11100 

11101 
11101 
11110 
11111 
11111 

01111 
11111 
11111 
11111 
11111

輸出




思路:

二進位制儲存25盞燈的開關情況,再BFS列舉所由變的方法。

為了節省效率,不用在300組測試樣例中每組都BFS,可以再開頭就算好6步以內可以由全部都是開的變成的所有情況,把步數記下,輸入後就直接查詢即可。

在進行開關時,用位運算把第k位改變的操作為 x^(1<<(k-1)) ,要注意邊界的判斷,改變左右的燈時,要判斷的是是否超出了這一行的邊界,而不僅僅是判斷是否超出了25和0。

程式碼:

#include <cstdio>
#include <iostream>
#include <queue>
#include <map>
using namespace std;

struct  Light {
	int x;
	int num;
	Light(int a,int b) {
		x=a;
		num=b;
	}
};

int Change(int x,int y) {
	x=x^(1<<(y-1));
	if(y+5<=25) {
		x=x^(1<<(y+4));
	}
	if(y-5>0) {
		x=x^(1<<(y-6));
	}
	if(y%5!=0) {
		x=x^(1<<(y));
	}
	if(y%5!=1) {
		x=x^(1<<(y-2));
	}
	return x;
}

map<int,int> use;

int bfs(int x) {
	queue<Light> que;
	que.push(Light(x,0));
	use[x]=0;
	while(!que.empty()) {
		Light head=que.front();
		que.pop();
		if(head.num>=6) {
			return -1;
		}
		for(int i=1; i<=25; i++) {
			int now=Change(head.x,i);
			if(!use.count(now)) {
				use[now]=head.num+1;
				que.push(Light(now,head.num+1));
			}
		}
	}
	return -1;
}

int main() {
	bfs(33554431);
	int t;
	scanf("%d",&t);
	while(t--) {
		int a[30]= {0};
		for(int i=0; i<5; i++) {
			string y;
			cin>>y;
			for(int j=0; j<5; j++) {
				a[i*5+j]=y[j]-'0';
			}
		}
		int x=0;
		int z=1;
		for(int i=24; i>=0; i--) {
			x+=z*a[i];
			z*=2;
		}
		if(use.count(x))
			printf("%d\n",use[x]);
		else
			printf("-1\n");
	}

	return 0;
}