問題 E: 費解的開關
時間限制: 1 Sec 內存限制: 128 MB提交: 13 解決: 7
[提交] [狀態] [討論版] [命題人:admin]
題目描述
你玩過“拉燈”游戲嗎?25盞燈排成一個5x5的方形。每一個燈都有一個開關,游戲者可以改變它的狀態。每一步,游戲者可以改變某一個燈的狀態。游戲者改變一個燈的狀態會產生連鎖反應:和這個燈上下左右相鄰的燈也要相應地改變其狀態。
我們用數字“1”表示一盞開着的燈,用數字“0”表示關着的燈。下面這種狀態
10111
01101
10111
10000
11011
在改變了最左上角的燈的狀態后將變成:
01111
11101
10111
10000
11011
再改變它正中間的燈后狀態將變成:
01111
11001
11001
10100
11011
給定一些游戲的初始狀態,編寫程序判斷游戲者是否可能在6步以內使所有的燈都變亮。
我們用數字“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組,每組數據有5行,每行5個字符。每組數據描述了一個游戲的初始狀態。各組數據間用一個空行分隔。
對於30%的數據,n<=5;
對於100%的數據,n<=500。
輸出
輸出數據一共有n行,每行有一個小於等於6的整數,它表示對於輸入數據中對應的游戲狀態最少需要幾步才能使所有燈變亮。
對於某一個游戲初始狀態,若6步以內無法使所有燈變亮,請輸出“-1”。
對於某一個游戲初始狀態,若6步以內無法使所有燈變亮,請輸出“-1”。
樣例輸入
3
00111
01011
10001
11010
11100
11101
11101
11110
11111
11111
01111
11111
11111
11111
11111
樣例輸出
3
2
-1
用二進制存每個狀態,然后對全是1的狀態進行反向BFS,存下六步內的所有狀態,用map存下這個狀態,再對比就行了。
#include <bits/stdc++.h>
using namespace std;
int get_map(int x,int i)
{
x=x^(1<<i);
if((i%5)<4)
{
x=x^(1<<(i+1));
}
if(i%5)
{
x=x^(1<<(i-1));
}
if(i>=5)
{
x=x^(1<<(i-5));
}
if(i<20)
{
x=x^(1<<(i+5));
}
return x;
}
map<int,int> Map;
void bfs()
{
queue<int> q;
q.push((1<<25)-1);
Map[(1<<25)-1]=1;
while(!q.empty())
{ int now=q.front();
q.pop();
if(Map[now]==7) return;
for(int i=0;i<25;i++)
{
int nex=get_map(now,i);
if(Map[nex]==0)
{
Map[nex]=Map[now]+1;
q.push(nex);
}
}
}
}
int main()
{
int n;
cin>>n;
bfs();
while(n--)
{
int i,y=0,x=0;
for(i=0;i<25;i++)
{
scanf("%1d",&y);
x+=(y<<i);
}
cout<<Map[x]-1<<endl;
}
return 0;
}
