BFS(廣搜) 翻幣問題
阿新 • • 發佈:2019-02-13
SSL 1457
題目描述
有N個硬幣(6<=N<=20000)全部正面朝上排成一排,每次將其中5個硬幣翻過來放在原位置,直到最後全部硬幣翻成反面朝上為止。試程式設計找出步數最少的翻法,輸出最少步數及翻法。
溫馨提示
如果你是SSL的學生,做之前請看這個:
題目分析
可以看得出,選擇其中5枚硬幣翻過來會有六種不同的情況:
1代表反過來的,0代表正面朝上的
翻過之前 翻過之後
五個正面 五個反面
四正一反 四反一正
三正二反 二反三正
二正三反 三反二正
一正四反 四正一反
五個反面 五個正面
所以說這是一棵六叉樹。
主要就是判斷組硬幣滿不滿足翻的條件(即不能將五個正面翻成二反三正之類的)
還有判斷這種正與反的情況有沒有出現過(大膽用迴圈,不會超時),就不會有這樣的情況:
1:11111
2:00000
3:11111
4:00000
…
就是無限翻同一種翻法,會死迴圈。
var
n,k:longint;
f:array[1..20000]of longint;
s:array[1..20000]of longint;
function check(x,y,l:longint):boolean;
var
i:longint;
begin
for i:=1 to x do
if s[i]=s[y]-l+5-l then exit(false);
exit(true);
end;
procedure print(x:longint);
begin
if x=0 then exit;
print(f[x]);
writeln(k,':' ,s[x]);
inc(k);
end;
procedure bfs;
var
h,t,i:longint;
begin
h:=0;t:=1;f[1]:=0;
s[1]:=n;
repeat
inc(h);
for i:=0 to 5 do
if (check(t,h,i)) and ((s[h]>=i)and(n-s[h]>=5-i)) then
begin
inc(t);
f[t]:=h;
s[t]:=s[h]-i+5-i;
if s[t]=0 then
begin
print(t);
exit;
end;
end;
until h=t;
end;
begin
readln(n);
bfs;
writeln(k-1);
end.