题目描述:
你玩过“拉灯”游戏吗?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”。
样例输入:
3
00111
01011
10001
11010
11100
11101
11101
11110
11111
11111
01111
11111
11111
11111
11111
样例输出:
3
2
-1
疾风剑客提供了一个相当快的算法,它的算法能在相当短的时间里算出给定状态到最终状态所需要的步数:对于每个状态,算法只需要枚举第一行改变哪些灯的状态,只要第一行的状态固定了,接下来的状态改变方法都是唯一的:每一行需要改变状态的位置都在上一行中不亮的灯的正下面,因为只有这样才能使上一行的灯全亮。我们枚举第一行的状态改变方法(共2^5种),对于每种方法都依次改变下面几行的状态使上面一行灯全亮。到最后一行我们需要判断是否最后一行也恰好全亮,并更新最小步数。好像这个算法能在0ms内出结果。
以下的程序是该枚举思想(BFS搞不了)
代码
1 program project1;
2 var
3 n,z,i,j,i1,i2,i3,i4,i5,m,ans:integer;
4 yes,found:boolean;
5 c:char;
6 a,aa:array[0..6,0..6]of integer;
7
8 procedure change(i,j:integer);
9 begin
10 a[i,j]:=1-a[i,j];
11 a[i-1,j]:=1-a[i-1,j];
12 a[i,j-1]:=1-a[i,j-1];
13 a[i,j+1]:=1-a[i,j+1];
14 a[i+1,j]:=1-a[i+1,j];
15 end;
16
17 begin
18 assign(input,'switch.in');
19 reset(input);
20 assign(output,'switch.out');
21 rewrite(output);
22 readln(n);
23 for z:=1 to n do
24 begin
25 for i:=1 to 5 do
26 begin
27 for j:=1 to 5 do
28 begin
29 read(c);
30 if c='0' then
31 aa[i,j]:=0
32 else
33 aa[i,j]:=1;
34 end;
35 readln;
36 end;
37 ans:=6;
38 yes:=false;
39 for i1:=0 to 1 do
40 for i2:=0 to 1 do
41 for i3:=0 to 1 do
42 for i4:=0 to 1 do
43 for i5:=0 to 1 do
44 begin
45 a:=aa;
46 m:=0;
47 if i1=1 then begin change(1,1);inc(m);end;
48 if i2=1 then begin change(1,2);inc(m);end;
49 if i3=1 then begin change(1,3);inc(m);end;
50 if i4=1 then begin change(1,4);inc(m);end;
51 if i5=1 then begin change(1,5);inc(m);end;
52 for i:=2 to 5 do
53 begin
54 for j:=1 to 5 do
55 if a[i-1,j]=0 then
56 begin
57 change(i,j);
58 inc(m);
59 if m>ans then
60 break;
61 end;
62 if m>ans then
63 break;
64 end;
65 if m>ans then
66 continue;
67 found:=true;
68 for i:=1 to 5 do
69 if a[5,i]=0 then begin
70 found:=false;
71 break;
72 end;
73 if found then
74 begin
75 yes:=true;
76 if m<ans then
77 ans:=m;
78 end;
79 end;
80 if yes then
81 writeln(ans)
82 else
83 writeln(-1);
84 readln;
85 end;
86 close(input);
87 close(output);
88 end.

浙公网安备 33010602011771号