| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 955 人关注过本帖
标题:八皇后问题
只看楼主 加入收藏
mayao_1989
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2009-9-23
结帖率:0
收藏
已结贴  问题点数:20 回复次数:3 
八皇后问题
如何用汇编递归解决八皇后问题?求高手指点。感激不尽。
搜索更多相关主题的帖子: 皇后 
2009-09-23 20:36
xiaosaner3
Rank: 2
等 级:论坛游民
威 望:1
帖 子:7
专家分:20
注 册:2009-9-22
收藏
得分:20 
这个嘛..

C语言我会, 你用汇编语言实现就行了
2009-09-30 18:20
阿贝
Rank: 2
等 级:论坛游民
威 望:1
帖 子:104
专家分:66
注 册:2009-10-22
收藏
得分:0 
这是用C语言写的,楼主参考下
#include "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;iColumn<8;iColumn++)
  printf("%c ",Queen[iLine][iColumn]);
  printf("\n"screen.width/2)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;
  }
  }
  }
  /****************************************************************************
  *这段代码是1991年国际模糊C代码大赛的“最佳小程序”,求解n皇后问题
  */
  #include<stdio.h>  
  int v,i,j,k,l,s,a[99];  
  main()  
  {  
  for(scanf("%d",&s);
  *a-s;
  v=a[j*=v]-a, k=i<s, j+=(v=j<s&&(!k&&!!printf(2+"\n\n%c"-(!l<<!j), " #Q"[l^v?(l^j)&1:2])&&++l||a<s&&v&&v-i+j&&v+i-j&&v+i-j))&&!(l%=s), v||(i==j?a[i+=k]=0:++a)>=s*k&&++a[--i]);  
  }
2009-10-23 23:10
阿贝
Rank: 2
等 级:论坛游民
威 望:1
帖 子:104
专家分:66
注 册:2009-10-22
收藏
得分:0 
苦心找了个用汇编写的,::


;程序功能:用深度优先搜索法解决八皇后问题并打印结果.
;列数行数分别用1-8标记.所以八皇后的位置申请了9个
 
;调试感慨:汇编调试实在麻烦,不像C中在任何地方加个printf就可以知道
;哪错了.跳来跳去的,不知哪里死循环了,实在不好调试.
 
 
.model small,stdcall
 
;由于皇后位置都是一位数,所以加上30H后作字符打印出.  
printResult macro
 local again,print,first
 push si ;不能改变它的值.
 
 mov ah,02h ;输出状态不变.
 mov cx,2 ;对称的结果,所以打两个结果.
again:  
 mov si,1  
print:
 mov dl,queen[si]
 cmp cx,2
 je first
 mov bl,9
 sub bl,dl
 mov dl,bl
first:
 add dl,30h
 int 21h
 inc si
 cmp si,9 ;到第9个就是说打完了.
 jnz print
 mov dl,' ' ;输出两个空格,为好看.
 int 21h
 int 21h
 loop again
 
 pop si
 endm
 
.data
 ;改来改去,何必那么小气呢?用9个多方便,就一个字节,不必这么小气!
 queen db 9 dup(0)
 used db 9 dup(0)  
 Nresult dw 0 ;结果的个数.
 
 
 prompt db "The positions are:",0ah,0dh,'$'
 over db 0ah,0dh,"The number of the result is $"
.code
 
;函数功能:把存在ax寄存器里的二进制数用十进制打印出来.
printaxd proc near
 mov bx,10000d ;二个字节的数最大就3万多.
 mov ch,0 ;还没出现第一个要打印的数(最高位的非0不需要打印)
 mov cl,5 ;最多有五位,所以一共除五次.
 mov si,ax ;哈哈,寄存器太聪明了.
go:
 mov ax,si
 mov dx,0 ;既然是除法,就要保证高位的绝对值最小.
 div bx
 dec cl ;除一次就减一次.
 mov di,ax ;除完就把商移走,位置让出来给bx/10
 mov si,dx ;保证余数.
 
 ;实现bx/10.
 mov ax,bx
 mov bx,10 ;记住乘除法运算不能用立即数.
 mov dx,0 ; 实际上dl的最大值也就是9小于10,但为了保险和习惯,还是用这一句.
 div bx
 mov bx,ax
 mov ax,di  
 cmp cl,0 ;如果到最后一位了,无论是0还是不为0,都要打印了.
 jz next
 or ch,al
 jz go
next:
 mov ch,1 ;有打印的了
 mov dl,al
 add dl,30h
 mov ah,02h
 int 21h
 cmp cl,0
 jnz go
 
 ret ; This line cann't be forgotten.
printaxd endp
 
main proc far
 mov ax,@data
 mov ds,ax
 mov es,ax
 
 mov dx,offset prompt
 mov ah,09h
 int 21h
 
 mov si,1 ;当然是从第一列开始.
go:
 inc queen[si] ;当前列向下走一步.
 
 ;测试是否走出8*8的格子了
 cmp queen[si],9
 jnz stay
 
 ;刚好踏出格子,就把当前列置0,把上一列所在行置空,然后继续go.
 mov queen[si],0
 dec si
 ;取消所占的行.
 mov al,queen[si] ;不知何以不能用movzx di,queen[si]
 cbw
 mov di,ax
 mov used[di],0
 ;是否完成搜索.
 cmp si,1
 jnz go
 ;调试记语:为什么为5时不退出呢?改成4后结果居然对了.最后一个疑问了!
 ;对!原来如此!退出是要在queen[1]为5时,当4变成5时,这个增加的过程
 ;在go的第一句,也就是说此时还为4.
 ;于是退出条件就是当此时第一列为4而又要向前址走一步时根据对称性
 ;就要退出了.
 cmp queen[si],4 ;利用对称性,如果第一列算到5行,就不用算了.
 je exit
 jmp go
 
stay:  ;留在方格内,那么就剩下是否满足不在同一行同一斜行的问题了.
 mov al,queen[si] ;不知何以不能用movzx di,queen[si]
 cbw
 mov di,ax
 cmp used[di],1 ;如果为1就说明当前列的当前行已使用.
 je go
 
 ;循环检查是否有在同一斜行的皇后.
 mov di,si
 dec di ; bx指向与当前列比较的列.
check:
 cmp di,0
 je checkover
 mov dx,si ;dx装着当前列与检测列的差.,差最大不过7,所以也可以说是装在dl中.
 sub dx,di
 mov al,queen[si]  ;al放两列的行之差.
 sub al,queen[di]
 cmp al,dl ;相等或相反就是在同一斜行.
 je go
 neg al ;求负数.
 cmp al,dl
 je go
 dec di
 jmp check
checkover:
 ;好,现在可以留下来了.
 cmp si,8
 jz result
 ;如果不是最后一列.
 mov al,queen[si] ;不知何以不能用movzx di,queen[si]
 cbw
 mov di,ax
 mov used[di],1 ;留下来这一行就占住了.
 inc si
 jmp go
 
result: ;好,一个结果出来了,根据对称,实际出来两个结果.
 add Nresult,2
 printResult
 mov queen[si],0
 dec si
 
 ;这四行初为设计上的漏洞,想了老半天.
 mov al,queen[si] ;不知何以不能用movzx di,queen[si]
 cbw
 mov di,ax
 mov used[di],0
 
 jmp go
  
exit:
 mov dx,offset over
 mov ah,09h
 int 21h
 mov ax,Nresult
 call printaxd
 mov ah,01h ; to pause
 int 21h
 
 mov ah,4ch
 int 21h
 
main endp
end main
  
 
 

本文来自CSDN博客,转载请标明出处:http://blog.
2009-10-23 23:13
快速回复:八皇后问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.015067 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved