高分求人工智能N皇后回溯算法vb程序,明早之前!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高分求人工智能N皇后回溯算法vb程序,明早之前!相关的知识,希望对你有一定的参考价值。
四皇后或八皇后或者N皇后都可以,要vb的,把结果写进文件中.我今晚写不出的话可以参考一下.(别整C的,版本太多了)
N皇后的回溯算法会员推荐 阅读1次 2006-1-24
Option Explicit
''N皇后互不攻击问题的回溯算法
Private Sub Command1_Click()
Dim n As Long
Dim i As Long, j As Long
Dim a() As Long
n = CLng(Text1.Text)
ReDim a(1 To n)
For i = 1 To n
a(i) = 1
Next
'*算法实现
'设i-1个皇后已经放好,判断第i个皇后的位置,如果和前面i-1个中的任意一个有攻击,则该皇后向前走一步.
'直到放好为止,如果该行没有位置可放,则表示前i-1个皇后的位置有问题,先将该第i个皇后回到第一列,
'再回溯到第i-1个皇后,将该皇后向前走一步,直到放好为止,如果不行,先将该皇后回一列,再回溯到第i-2个皇后.
'如此,直到所有皇后放好为止.
'---------------------------------------------------------------------------------------------
For i = 2 To n
10:
If a(i) <= n Then
For j = 1 To i - 1
If a(j) = a(i) Or Abs(a(i) - a(j)) = i - j Then a(i) = a(i) + 1: GoTo 10
Next
If i = n Then MsgBox "有解" ''要求多解的话,可以再继续
Else
a(i) = 1
i = i - 1
a(i) = a(i) + 1
If i = 1 Then
If a(i) > n Then MsgBox "无解": Exit Sub
i = 2
End If
GoTo 10
End If
Next
'---------------------------------------------------------------------------------------------
grd.Rows = 0
grd.Cols = 0
grd.Rows = n + 1
grd.Cols = n + 1
For i = 0 To n
grd.TextMatrix(0, i) = i
grd.TextMatrix(i, 0) = i
grd.ColWidth(i) = 225
Next
For i = 1 To n
grd.TextMatrix(i, a(i)) = "*"
Next
End Sub
参考资料:http://edu.admin188.com/jc/NET/83805.html
参考技术A 应该可以的,如果有空可以把“\”删掉,不影响大局。var i,j,n:integer;
a:array[1..11] of 0..11; 放皇后数组
b:array[2..2*11] of boolean; 对角线标志数组
c:array[-(11-1)..11-1] of boolean; 对角线标志数组
col:array[1..11] of boolean; 列标志数组
total:integer; 统计总数
procedure output; 输出
var i:integer;
begin
write('No.\':4,'[\',total+1:2,']\');
for i:=1 to n 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 n do 每一行均有max种放法
if ok(i,dep) then begin
a[dep]:=i;
b[i+dep]:=false; /对角线已放标志
c[dep-i]:=false; \\对角线已放标志
col[i]:=false; 列已放标志
if dep=n then output
else try(dep+1); 递归下一层
a[dep]:=0; 取走皇后,回溯
b[i+dep]:=true; 恢复标志数组
c[dep-i]:=true;
col[i]:=true;
end;
end;
begin
read(n);
for i:=1 to n do begin a[i]:=0;col[i]:=true;end;
for i:=2 to 2*n do b[i]:=true;
for i:=-(n-1) to n-1 do c[i]:=true;
total:=0;
try(1);
writeln('total:\',total);
end.
N皇后问题(递归回溯)
今天讲了N后问题,现在来复习一下。
N后问题就是在N*N格的棋盘上面放置彼此不受攻击的n个皇后。这里的皇后指的是国际象棋中的皇后,按照国际象棋的规则,皇后可以攻击当前行和当前列还有同一斜线的棋子。简单来说,就是n个皇后的位置不可以在同一行,同一列,同一斜线。因为这几天学习的是回溯算法,很简单的想到了回溯。这个问题也是经典的回溯算法习题之一。
下面来想一下问题所包含的条件,明显的条件就是棋盘是n*n,而且很简单就想到n个皇后不可以在同一列,就是每一列都会有一个皇后。下面就是隐式的条件了,同一行和同一列都可以很简单的解决,同一斜线不是很好想。后来发现同一斜线的皇后都是皇后的位置差和皇后所在的列相等。就是皇后的位置斜率为1。翻译为代码语言就是,皇后所在的位置的差的绝对值等于皇后的列的差的绝对值。这个后面还会讲一下。条件都讲完了,下面就说一说算法的主体。
算法的主体是由递归构成,递归的参数就是当前考虑的皇后的列,为了下面的计算方便,这里将皇后的个数和数组都传了进去。为什么传进去数组?因为自己一开始想的是一个二维数组,这个也是大家容易想到的,但是后来发现,解的形式和数组的下标有关,干脆将二维数组变为了一维数组,将皇后所在的列变为数组的下标。这样,就省去了很多的无用功。递归的边界就是k的位置大于等于n。递归的主体是一个for循环,将循环的值赋值给数组当前的位置,同时检验当前位置是否正确,如果正确就进行下一个递归(k的值加一),不正确就进行下一次循环。讲到了检验k的位置,就说一说这个方法,很简单,就是判断当前位置是不是符合问题的条件,要有一个返回值,方便后面的调用。检验的时候也是要用到for循环。
算法的主体讲完了,下面就直接粘贴代码,代码如下:
package sf; import java.util.Scanner; //N后问题 public class demo7 { public static int num=0;//累加和 //判断当前位置是否正确 public static Boolean judge(int[] p,int k) { for(int i=0;i<k;i++) { //绝对值的判定和列的判定。(不用判定行) if((Math.abs(i-k)==Math.abs(p[i]-p[k]))||(p[i]==p[k])) { return false; } } //要注意这个return的位置,在这里是为了让for循环能够一直循环下去,不被中间的位置打断,可以将 //这个return放到for循环中体验一下。会发现,解的个数会变多。 return true; } //算法主体 递归回溯 k为当前考虑位置 public static void Queen(int[] p,int n,int k) { //这里的方法主体还是要多想一想 if(k>=n) { num++; //打印结果 for(int i=0;i<n;i++) System.out.print(p[i]); System.out.println(""); }else{ for(int j=1;j<=n;j++) { //System.out.println(k); //将皇后的位置赋值给数组中的元素,相当于放置皇后 p[k]=j; if(judge(p, k)) { //递归下一个位置 Queen(p, n, k+1); } } } } public static void main(String[] args) { System.out.println("请输入皇后的个数:"); Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int []p=new int[n]; Queen(p,n,0); //将结果打印出来,如果只是打印这一个计数,程序的运行会快一点。 System.out.println(n+"皇后问题的解共:"+num+"种"); } }
算法的代码就是这样,算法的主体还是不好想的,我想了一会,感觉还是存在着一些问题,但是代码执行的结果正确,就不在想了。要注意算法中的for循环的指针的大小,这里还是要想一想的,虽然只有简单的一维数组。下面就讲一讲自己的一些想法,这个算法就是简单的递归求解,说的明白一点,就是穷举法,这就是这个算法的不足之处。只是在简单的列举之后,并没有进行函数限制。这个和回溯的思想有些不一样,回溯的思想是算法的主体还要有函数限制,将后面的解的一些错误的子树直接去掉,这个算法没有做到这一步,算法的实现还是有很大的提升空间,大概在求16皇后问题的时候需要100秒就是算法的大概极限了(这个也是在网上看到的),自己还是一个菜鸟,现在就是想一想。还是理解回溯的思想,在穷举的时候对于结果进行函数限制,方便后面的列举,大大加快算法的效率。
以上是关于高分求人工智能N皇后回溯算法vb程序,明早之前!的主要内容,如果未能解决你的问题,请参考以下文章