高分求人工智能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程序,明早之前!的主要内容,如果未能解决你的问题,请参考以下文章

回溯算法

回溯法-N皇后问题-C++算法

数据结构 | 回溯算法

暴力穷举和回溯法(八皇后问题)

n皇后问题(C语言 回溯算法)

n皇后问题(C语言 回溯算法)