1. 程式人生 > >BFS(廣搜) 翻幣問題

BFS(廣搜) 翻幣問題

SSL 1457
題目描述
有N個硬幣(6<=N<=20000)全部正面朝上排成一排,每次將其中5個硬幣翻過來放在原位置,直到最後全部硬幣翻成反面朝上為止。試程式設計找出步數最少的翻法,輸出最少步數及翻法。

溫馨提示
如果你是SSL的學生,做之前請看這個:
圖源——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.