N皇后问题的回溯法求解属于子集树还是排列树 详细讲一讲

N皇后的算法求解用的是子集树的算法框架,但是可以只凭这个就确定吗? 希望能详细讲一讲。还有子集树跟排列树都举几个例子。谢谢。

“八皇后”问题递归法求解 (Pascal语言) 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。现代教学中,把八皇后问题当成一个经典递归算法例题。 算法分析:数组a、b、c分别用来标记冲突,a数组代表列冲突,从a[0]~a[7]代表第0列到第7列,如果某列上已经有皇后,则为1,否则为0;数组b代表主对角线冲突,为b[i-j+7],即从b[0]~b[14],如果某条主对角线上已经有皇后,则为1,否则为0;数组c代表从对角线冲突,为c[i+j],即从c[0]~c[14],如果某条从对角线上已经有皇后,则为1,否则为0;另优化:第一个皇后在1~4格,最后*2,即为总解数 } program queens; var a:array [1..8] of integer; b,c,d:array [-7..16] of integer; t,i,j,k:integer; procedure print; begin t:=t+1; write(t,': '); for k:=1 to 8 do write(a[k],' '); writeln; end; procedure try(i:integer); var j:integer; begin for j:=1 to 8 do {每个皇后都有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; if i<8 then try(i+1) {8个皇后没有摆完,递归摆放下一皇后} else print; {完成任务,打印结果} b[j]:=0; {回溯} c[i+j]:=0; d[i-j]:=0; end; end; begin fillchar(a,sizeof(a),0); {初始化数组} fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); fillchar(d,sizeof(d),0); try(1);{从第1个皇后开始放置} end. “八皇后”问题递归法求解 (C语言) #i nclude "stdio.h" static char Queen[8][8]; static int a[8]; static int b[15]; static int c[15]; static int iQueenNum=0; //记录总的棋盘状态数 void qu(int i); //参数i代表行 int main() { int iLine,iColumn; //棋盘初始化,空格为*,放置皇后的地方为@ for(iLine=0;iLine<8;iLine++) { a[iLine]=0; //列标记初始化,表示无列冲突 for(iColumn=0;iColumn<8;iColumn++) Queen[iLine][iColumn]='*'; } //主、从对角线标记初始化,表示没有冲突 for(iLine=0;iLine<15;iLine++) b[iLine]=c[iLine]=0; qu(0); return 0; } void qu(int i) { int iColumn; for(iColumn=0;iColumn<8;iColumn++) { if(a[iColumn]==0&&b[i-iColumn+7]==0&&c[i+iColumn]==0) //如果无冲突 { Queen[iColumn]='@'; //放皇后 a[iColumn]=1; //标记,下一次该列上不能放皇后 b[i-iColumn+7]=1; //标记,下一次该主对角线上不能放皇后 c[i+iColumn]=1; //标记,下一次该从对角线上不能放皇后 if(i<7) qu(i+1); //如果行还没有遍历完,进入下一行 else //否则输出 { //输出棋盘状态 int iLine,iColumn; printf("第%d种状态为:\n",++iQueenNum); for(iLine=0;iLine<8;iLine++) { for(iColumn=0;iColumn2)this.width=screen.width/2" vspace=2 border=0>; } printf("\n\n"screen.width/2)this.width=screen.width/2" vspace=2 border=0>; } //如果前次的皇后放置导致后面的放置无论如何都不能满足要求,则回溯,重置 Queen[iColumn]='*'; a[iColumn]=0; b[i-iColumn+7]=0; c[i+iColumn]=0; } } } 八皇后的c语言解法: #include #include #include int n,k,a[20],num=0; int attack(int k){ int flag=0; int i=1; while ((i<k)&&(a[k]!=a)&&(fabs(a[k]-a)!=(k-i))) i++; if (i==k) flag=1; return flag; } void place(int k) { //printf(" %d",k); int i; if (k==n+1){ num=num+1; printf("num=%d:",num); for (i=1;i<n+1;i++) printf(" %d",a); printf("\n");} else { for (i=1;i<n+1;i++){ a[k]=i; if (attack(k)==1) place(k+1); else a[k]=0; } } } main(){ scanf("%d",&n); k=1; place(k); if (k!=n+1) printf("no solution!\n"); getch(); }
温馨提示:答案为网友推荐,仅供参考