題目
你玩過「拉燈」遊戲嗎?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輸入樣例:
300111
01011
10001
11010
11100
1110111101
11110
11111
11111
01111輸出樣例:11111
11111
11111
11111
32-1分析
費解開關最關鍵的是乙個燈變了,它的上下左右四個方向都要改變,那麼,我們的想法就是,固定某些燈,讓另外一些燈的開關選擇變為唯一(只能是按或則不按)
我們先選擇乙個固定的方向,假如是從上往下,當第一行的狀態確定了,後幾行燈的狀態就唯一確定了(從上往下一次操作,當第一行的狀態確定了,那麼可以改變第一行狀態就只有第二行的燈的狀態)
小知識:
1.一行5個數,可以用遞迴列舉每個數,也可用二進位制數來列舉每個數,25是32,那麼1-31代表著25的每一種狀態
2.判斷乙個數的上下左右,用偏移量來做,定義乙個dx[5]=,dy[5]=用當前狀態加上偏移量得到當前數上下左右的乙個座標
最開始有點不理解,for(int op=0;op<32;op++)這一步,覺得燈的所有狀態都是已知是,原狀態第一行變為op的狀態需要的不止要step++一步,後來才看懂,op只是列舉出第一行可以修改的32方案,間接改變的是第一行的燈的狀態。
#include
#include
using
namespace std;
const
int n=6;
char g[n]
[n],backup[n]
;int dx[5]
=,dy[5]
=;void
turn
(int x,
int y)
}int
main()
for(
int i=
0;i<
4;i++
)//從第一排起,第一排的燈是否亮直接決定後一排的開關是否按下
for(
int j=
0;j<
5;j++)if
(g[i]
[j]==
'0')
//燈沒有亮
bool dark=
false
;for
(int i=
0;i<
5;i++
)//不是每一種方案都能保證燈全亮,所以最後要檢驗一哈最後一排的燈是否是亮著的
if(g[4]
[i]==
'0')if(
!dark)rest=
min(rest,step)
;//恢復原狀態
memcpy
(g,backup,
sizeof g);}
if(rest>
6)rest=-1
;
cout<}return0;
}
AcWing 費解的開關
你玩過 拉燈 遊戲嗎?25盞燈排成乙個5x5的方形。每乙個燈都有乙個開關,遊戲者可以改變它的狀態。每一步,遊戲者可以改變某乙個燈的狀態。遊戲者改變乙個燈的狀態會產生連鎖反應 和這個燈上下左右相鄰的燈也要相應地改變其狀態。我們用數字 1 表示一盞開著的燈,用數字 0 表示關著的燈。下面這種狀態 101...
acwing 95 費解的開關
時 空限制 1s 256mb 你玩過 拉燈 遊戲嗎?25盞燈排成乙個5x5的方形。每乙個燈都有乙個開關,遊戲者可以改變它的狀態。每一步,遊戲者可以改變某乙個燈的狀態。遊戲者改變乙個燈的狀態會產生連鎖反應 和這個燈上下左右相鄰的燈也要相應地改變其狀態。我們用數字 1 表示一盞開著的燈,用數字 0 表示...
AcWing 95 費解的開關
你玩過 拉燈 遊戲嗎?25盞燈排成乙個5x5的方形。每乙個燈都有乙個開關,遊戲者可以改變它的狀態。每一步,遊戲者可以改變某乙個燈的狀態。遊戲者改變乙個燈的狀態會產生連鎖反應 和這個燈上下左右相鄰的燈也要相應地改變其狀態。我們用數字 1 表示一盞開著的燈,用數字 0 表示關著的燈。下面這種狀態 101...