八皇后问题(递归求解)
八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题(这节课小甲鱼先用递归算法来解)。该问题是十九世纪著名的数学家高斯1850年提出:
在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯先生当年由于没有学好计算机编程,没日没夜地计算呀,得出结论是76种,硬生生把自己给“搞死”了!
对了,当年还没有计算机……
视频讲解:http://blog.fishc.com/2228.html
源代码参考:http://bbs.fishc.com/thread-28183-1-1.html 下载看看 虽然目前对递归还不怎么了解 Dim a(8, 8)
For i = 0 To 7
For j = 0 To 7
a(i, j) = 0
Next
Next
num=1
For n0 = 0 To 7
a(0, n0) = 1
hang0=n0
For n1 = 0 To 7
If safe(1, n1) = 1 Then
a(1, n1) = 1
hang1=n1
For n2 = 0 To 7
If safe(2, n2) = 1 Then
a(2, n2) = 1
hang2=n2
For n3 = 0 To 7
If safe(3, n3) = 1 Then
a(3, n3) = 1
hang3=n3
For n4 = 0 To 7
If safe(4, n4) = 1 Then
a(4, n4) = 1
hang4=n4
For n5 = 0 To 7
If safe(5, n5) = 1 Then
a(5, n5) = 1
hang5=n5
For n6 = 0 To 7
If safe(6, n6) = 1 Then
a(6, n6) = 1
hang6=n6
For n7 = 0 To 7
If safe(7, n7) = 1 Then
a(7, n7) = 1
hang7=n7
Call printf()
num=num+1
End If
Next
a(7, hang7) = 0
End If
a(6, hang6) = 0
Next
End If
a(5, hang5) = 0
Next
End If
a(4, hang4) = 0
Next
End If
a(3, hang3) = 0
Next
End If
a(2, hang2) = 0
Next
End If
a(1, hang1) = 0
Next
a(0, hang0) = 0
Next
Sub printf()
p=""
For i = 0 To 7
For j = 0 To 7
P = P & CStr(a(i, j)) & " "
Next
P = P & vbCrLf
Next
MsgBox p, vbokonly, "第" & num & "种皇后位置!"
End Sub
Function safe(x, y)
For h= 0 To 7
For l = 0 To 7
If a(h, l) = 1 Then
If (h = x) or (l=y) or ((h - l)= (x - y)) or ((h + l) = (x + y)) Then
safe = 0
Exit Function
Else
safe = 1
End If
End If
Next
Next
End Function
强烈支持楼主ing…… 看我同学写的八皇后,多么雷人。。。#include <iostream>
#include <string>
using namespace std;
int pd(int i,int h,int j)
{
int t;
t=h*h*h*h*h*h*h*h*h;//列
t=t*h*h*h*h*h*h*h*h;//列
t=t*h*h*h*h*h*h*h*h;//行
t=t*h*h*h*h*h*h*h*h;//行
t=t*h*h*h*h*h*h*h*h;//xie
t=t*h*h*h*h*h*h*h*h;//xie
t=t*h*h*h*h*h*h*h*h;//xie
t=t*h*h*h*h*h*h*h*h;//xie
return t;
}
int main()
{
int h;
for (int qqq=0;qqq<30;qqq++)
{
for(int qq=0;qq<30;qq++)
{
h=1;
}
}
int n,m,k;
int y,e,sa,si,w,l,q,b,sum;
sum=0;
for (y=11;y<=18;y++)
{
h=0;//11
for (e=11;e<=18;e++)
{
if(pd(12,h,e)==0)//12
{
}
else
{
h=0;
for(sa=11;sa<=18;sa++)//13
{
if(pd(13,h,sa)==0)
{
}
else
{
h=0;
for (si=11;si<=18;si++)//14
{
if(pd(14,h,si)==0)
{
}
else
{
h=0;
for(w=11;w<19;w++)//15
{
if(pd(15,h,w)==0)
{
}
else
{
h=0;
for (l=11;l<=18;l++)//16
{
if(pd(16,h,l)==0)
{
}
else
{
h=0;
for (q=11;q<=18;q++)//17
{
if(pd(17,h,q)==0)
{
}
else
{
h=0;
for (b=11;b<=18;b++)//18
{
if(pd(18,h,b)==0)
{
}
else
{
sum++;
h=0;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
for (k=11;k<19;k++)
{
cout<<h;
}
cout<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;
}
}
for (n=18;n<30;n++)
{
for(m=0;m<30;m++)
{
h=1;
}
}
h=1;
}
}
h=1;
for (n=17;n<30;n++)
{
for(m=0;m<30;m++)
{
h=1;
}
}
}
}
h=1;
for (n=16;n<30;n++)
{
for(m=0;m<30;m++)
{
h=1;
}
}
}
}
h=1;
for (n=15;n<30;n++)
{
for(m=0;m<30;m++)
{
h=1;
}
}
}
}
h=1;
for (n=14;n<30;n++)
{
for(m=0;m<30;m++)
{
h=1;
}
}
}
}
h=1;
for (n=13;n<25;n++)
{
for(m=0;m<30;m++)
{
h=1;
}
}
}
}
for (n=12;n<30;n++)
{
for(m=0;m<30;m++)
{
h=1;
}
}
h=1;
}
cout<<sum<<endl;
return 0;
} andalousie 发表于 2014-2-22 13:10 static/image/common/back.gif
看我同学写的八皇后,多么雷人。。。
雅蠛蝶,一个比一个经典!!! 请求楼主帮忙
我的问题:八皇后我的理解是把所有结果遍历一遍楼主的代码从1——7行都有for(i=0;i<8;++i){EightQuee}
的遍历 为什么第一行只遍历了一次为什么结果不是8*92 强烈支持楼主ing…… 啊 {:1_1:} andalousie 发表于 2014-2-22 13:10
看我同学写的八皇后,多么雷人。。。
神人也~~~受我膜拜~~~~ 真是难得给力的帖子啊。 八皇后
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<conio.h>
#define N 8 //皇后数=棋盘行列数
int a; //a为第i行皇后所在列
void show() //图形化输出
{
int i;
int p,q ;
int b={0};
static int t=1;
printf("第%d个解为: ",t++);
for(i=0;i<N;i++)
{
b]=1;
printf("(%d,%d) ",i,a);
}
printf("\n");
for(p=0;p<N;p++)
{
for(q=0;q<N;q++)
{
if(b==1)
printf("●");
else
printf("○");
}
printf("\n");
}
}
int check(int n) //满足条件返回1,否则返回0
{
int i;
for(i=0;i<n;i++)
{
if(a==a||fabs(n-i)==fabs(a-a)) //at the same column or diagonal (对角线)
return 0;
}
return 1;
}
void put(int n) //在第n行放置第n个皇后
{
int i;
if(n==N)
return ;
for(i=0;i<N;i++)
{
a=i;
if(check(n)) //位置合法
{
if(n==N-1) //皇后全部放置完毕
show();
else
put(n+1);
}
}
}
int main ()
{
put(0);
return 0;
}
5L超神了{:10_247:}
下载看看 虽然目前对递归还不怎么了解
先看 #include<stdio.h>
#define N 8
int count=0;
int IsSafe(int row,int n,int (*chess))
{
//判断列,斜向是否有冲突
//情况分为5种,左上,左下,右上,右下,本列
int i,j;
int flag;
flag=1;//安全
for(i=0;i<N;i++) //本列
{
if( 1 == chess)
{
flag=0;
break;
}
}
for(i=row,j=n;i>=0&&j>=0;--i,--j)//左上
{
if( 1 == chess)
{
flag=0;
break;
}
}
for(i=row,j=n;i<N&&j>=0;++i,--j)//左下
{
if( 1 == chess)
{
flag=0;
break;
}
}
for(i=row,j=n;i>=0&&j<N;--i,++j)//右上
{
if( 1 == chess)
{
flag=0;
break;
}
}
for(i=row,j=n;i<N&&j<N;++i,++j)//右下
{
if( 1 == chess)
{
flag=0;
break;
}
}
return flag;
}
// 参数row: 表示起始行
// 参数n: 表示列数
// 参数(*chess): 表示指向棋盘每一行的指针
void EightQueen(int row,int n,int (*chess))//重点
{
//操作下标为 row 的那行
//复制整个棋盘
int chess2={0};
int i,j;
for(i=0;i<N;++i)//复制,形成副本,然后操作副本
{
for(j=0;j<N;++j)
chess2=chess;
}
//判断row==N,row==N代表溢出了,如果溢出了,就输出这种可能
//否则,继续填棋
if( N==row )//棋盘满了,输出副本
{
for(i=0;i<N;++i)
{
for(j=0;j<N;++j)
printf("%d ",chess2);
printf("\n");
}
printf("\n\n");
count++; //出现一种可能
}
else //无溢出,棋盘未满,继续填棋
{
for(j=0;j<N;++j)//填充本行 的0到N-1列
{
if(IsSafe(row,j,chess2))//1:安全,row行j列填棋
{
for(i=0;i<N;++i)
chess2=0;//为了数据安全,清空本行
chess2=1;//row行j列填棋
EightQueen(row+1,n,chess2);//填充下一行
}
}
}
}
//*(*(chess+i)+j) (*chess)
int main(int argc, char *argv[]) {
//主函数说明:
int chess={0};
EightQueen(0,N,chess);
printf("%d皇后有%d种可能!\n\n",N,count);
return 0;
}
本人的拙见 余錦濤 发表于 2019-11-21 23:31
本人的拙见
可以试试从列开始放皇后
页:
[1]