當前位置:編程學習大全網 - 源碼下載 - 求~~~pascal八皇後 非遞歸詳細算法和程序

求~~~pascal八皇後 非遞歸詳細算法和程序

〖問題描述〗

在壹個8×8的棋盤裏放置8個皇後,要求每個皇後兩兩之間不相"沖"(在每壹橫列豎列斜列只有壹個皇後)。

〖問題分析〗(聿懷中學呂思博)

這道題可以用遞歸循環來做,分別壹壹測試每壹種擺法,直到得出正確的答案。主要解決以下幾個問題:

1、沖突。包括行、列、兩條對角線:

(1)列:規定每壹列放壹個皇後,不會造成列上的沖突;

(2)行:當第I行被某個皇後占領後,則同壹行上的所有空格都不能再放皇後,要把以I為下標的標記置為被占領狀態;

(3)對角線:對角線有兩個方向。在同壹對角線上的所有點(設下標為(i,j)),要麽(i+j)是常數,要麽(i-j)是常數。因此,當第I個皇後占領了第J列後,要同時把以(i+j)、(i-j)為下標的標記置為被占領狀態。

2、數據結構。

(1)解數組A。A[I]表示第I個皇後放置的列;範圍:1..8

(2)行沖突標記數組B。B[I]=0表示第I行空閑;B[I]=1表示第I行被占領;範圍:1..8

(3)對角線沖突標記數組C、D。

C[I-J]=0表示第(I-J)條對角線空閑;C[I-J]=1表示第(I-J)條對角線被占領;範圍:-7..7

D[I+J]=0表示第(I+J)條對角線空閑;D[I+J]=1表示第(I+J)條對角線被占領;範圍:2..16

〖算法流程〗

1、數據初始化。

2、從n列開始擺放第n個皇後(因為這樣便可以符合每壹豎列壹個皇後的要求),先測試當前位置(n,m)是否等於0(未被占領):

如果是,擺放第n個皇後,並宣布占領(記得要橫列豎列斜列壹起來哦),接著進行遞歸;

如果不是,測試下壹個位置(n,m+1),但是如果當n<=8,m=8時,卻發現此時已經無法擺放時,便要進行回溯。

3、當n>;8時,便壹壹打印出結果。

〖優點〗逐壹測試標準答案,不會有漏網之魚。

〖參考程序〗queen.pas

----------------------------------------------------------------------------

programtt;

vara:array[1..8]ofinteger;

b,c,d:array[-7..16]ofinteger;

t,i,j,k:integer;

procedureprint;

begin

t:=t+1;

write(t,'');

fork:=1to8dowrite(a[k],'');

writeln;

end;

proceduretry(i:integer);

varj:integer;

begin

forj:=1to8do{每個皇後都有8種可能位置}

if(b[j]=0)and(c[i+j]=0)and(d[i-j]=0)then{判斷位置是否沖突}

begin

a:=j;{擺放皇後}

b[j]:=1;{宣布占領第J行}

c[i+j]:=1;{占領兩個對角線}

d[i-j]:=1;

ifi<8thentry(i+1){8個皇後沒有擺完,遞歸擺放下壹皇後}

elseprint;{完成任務,打印結果}

b[j]:=0;{回溯}

c[i+j]:=0;

d[i-j]:=0;

end;

end;

begin

fork:=-7to16do{數據初始化}

begin

b[k]:=0;

c[k]:=0;

d[k]:=0;

end;

try(1);{從第1個皇後開始放置}

end.

==========================================

這是N皇後問題,看看吧:

在N*N的棋盤上,放置N個皇後,要求每壹橫行每壹列,每壹對角線上均只能放置壹個皇後,問可能的方案及方案數。

const max=8;

var i,j:integer;

a:array[1..max] of 0..max; //放皇後數組

b:array[2..2*max] of boolean; // ‘/’對角線標誌數組}

c:array[-(max-1)..max-1] of boolean;// ‘\’對角線標誌數組}

col:array[1..max] of boolean; //列標誌數組}

total:integer; //統計總數}

procedure output; //這裏是輸出過程

var i:integer;

begin

write('No.':4,'[',total+1:2,']');

for i:=1 to max do write(a[i]:3);write(' ');

if (total+1) mod 2 =0 then writeln; inc(total);

end;

function ok(i,dep:integer):boolean; //判斷第dep行第i列可放否?

begin

ok:=false;

if ( b[i+dep]=true) and ( c[dep-i]=true) {and (a[dep]=0)} and

(col[i]=true) then ok:=true

end;

procedure try(dep:integer);

var i,j:integer;

begin

for i:=1 to max do //每壹行均有max種放法,對吧?xixi~~~~

if ok(i,dep) then begin

a[dep]:=i;

b[i+dep]:=false; // ‘/’對角線已放標誌

c[dep-i]:=false; // ‘\’對角線已放標誌

col[i]:=false; // 列已放標誌

if dep=max then output

else try(dep+1); // 遞歸下壹層

a[dep]:=0; //取走皇後,回溯

b[i+dep]:=true; //恢復標誌數組

c[dep-i]:=true;

col[i]:=true;

end;

end;

begin

for i:=1 to max do begin a[i]:=0;col[i]:=true;end;

for i:=2 to 2*max do b[i]:=true;

for i:=-(max-1) to max-1 do c[i]:=true;

total:=0;

try(1);

writeln('total:',total);

end.

  • 上一篇:誰能告訴我東北麻將室怎麽玩的?
  • 下一篇:倫敦帝國理工學院數學專業介紹
  • copyright 2024編程學習大全網