【八皇后问题】 回溯算法

回溯算法:
回溯算法实际上是一个类似枚举的搜索尝试方法,它的思想是在搜索尝试中寻找问题的解,当发现不满足求解条件时,就“回溯”返回,尝试别的路径。之前介绍的基础算法中的贪婪算法,动态规划等都具有“无后效性”,也就是在分段处理问题时,某状态一旦确定,将不再改变。而多数问题很难找到"无后效性”的阶段划分和相应决策,而是通过深入搜索尝试和回溯操作完成的。

八皇后问题:8*8的国际象棋棋盘中放八个皇后,是任意两个皇后不能互相吃掉。规则:皇后能吃掉同一行,同一列,同一对角线的任意棋子。

模型建立:不妨设八个皇后分别在第i行,那么解空间就是一个八个皇后所在列的序号,为n元一维向量(x1,x2,x3,x4,x5,x6,x7,x8),搜索空间是1<=Xi<=8,共8^8个状态。但正如之前所说,回溯法采用“走不通就掉头”,故实际算法不必搜索那么多的状态,例如,(1,1,x3,x4,x5,x6,x7,x8)的状态共有8^6个,由于1,2皇后不能在同一列,那么这8^6个状态是不会搜索的。

算法设计1:加约束条件的枚举算法
约束条件有三个:
不在同一列(Xi不等于Xj)
不在同一主对角线(Xi-i不等于Xj-j)
不在同以负对角线(Xi+i不等于Xj+j)
后两项可合并为fabs(Xi-Xj)不等于fabs(i-j)
那么直接贴代码了(此处代码较多,故以4皇后为例)

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int check(int a[],int n);
int main()
{
    int a[9],i;
    for(a[1]=1;a[1]<=4;a[1]++)
    {
        for(a[2]=1;a[2]<=4;a[2]++)
        {
            if(check(a,2)==0)continue;
            for(a[3]=1;a[3]<=4;a[3]++)
            {
                if((check(a,3)==0))continue;
                for(a[4]=1;a[4]<=4;a[4]++)
                {
                    if(check(a,4)==0)continue;
                    else {for(i=1;i<=4;i++)
                             cout << a[i]<< ‘ ‘;
                             cout << endl;}
                }
            }
        }
    }
    return 0;
}
int check(int a[],int n)
{
    int i;
    for(i=1;i<=n-1;i++)
    {
        if(fabs((double)(a[i]-a[n]))==fabs((double)(i-n))||a[i]==a[n])return 0;
    }
    return 1;
}

运行结果:
2  4  1  3
3  1  4  2

八皇后问题模版(非递归回溯算法)

#include <iostream>
#include <cmath>
using namespace std;
int a[20],n,cnt=0;
void backdate(int n);
int check(int k);
void output(int);
int main()
{
    cin >> n;
    backdate(n);
    return 0;
}
void backdate(int n)
{
    int k;
    a[1]=0;
    k=1;
    while(k>0)
    {
        a[k]++;
        while( (a[k]<=n) && (check(k)==0) ) //为第k个皇后搜索位置
        {
            a[k]++;
        }
        if(a[k]<=n)
        {
            if(k==n)    //找到一组解
                output(n);
            else
            {
                k=k+1;    //前k个皇后找到位置,继续为第k+1个皇后找到位置
                a[k]=0;    //注意下一个皇后一定要从头开始搜索
            }
        }
        else k=k-1;      //回溯(务必留意,此算法精华尽在于此!)
    }
}
int check(int k)
{
    int i;
    for(i=1;i<=k-1;i++)
    {
        if(fabs((double)(a[i]-a[k]))==fabs((double)(i-k))||a[i]==a[k])
            return 0;
    }
    return 1;
}
void output(int)
{
    int i;
    cnt++;  //测试用格外加的计数器
    for(i=1;i<=n;i++)
    {
        cout << a[i] << ‘ ‘;
    }
        cout << cnt << endl;
}

运行结果:
4(enter|)
2  4  1  3
3  1  4  2

时间: 2024-10-05 05:41:32

【八皇后问题】 回溯算法的相关文章

八皇后,回溯算法

public class Queue_8 { public int size = 4; //queue i can locate at (i,loc[i]) public int loc[] = new int[size+1]; // 求第k个元素,放置的位置, 与已经放过的皇后比较,如果它们在同一行或一列,或者在一条斜线上(斜线是根据横坐标和纵坐标的差值比较,如果在一条斜线上,横坐标差值就会等于纵坐标差值) public boolean place(int k){ int i; for(i=1

八皇后,回溯与递归(Python实现)

八皇后,回溯与递归(Python实现) 八皇后问题是十九世纪著名的数学家高斯1850年提出 .以下为python语言的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩展为九皇后,十皇后问题. 问题:在一个8*8棋盘上,每一行放置一个皇后旗子,且它们不冲突.冲突定义:同一列不能有两个皇后,每一个对角线也不能有两个皇后.当然,三个皇后也是不行的,四个也是不行的,凭你的智商应该可以理解吧. 解决方案:回溯与递归. 介绍: 1.回溯法 回溯

八皇后(JAVA算法实现)

在学习现代软件工程构建之法这门课时,老师要求发表一篇博客,使用JAVA算法实现八皇后问题的求解.写这篇博客时,我学习了一些其他的博客,因为我常常遇到问题,自己无法解决时,向他人学习也是一种方法. 国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 我们可以逐行或者逐列来进行可行摆放方案的遍历,每一行(或列)遍历出一个符合条件的 位置,接着就到下一行或列遍历下一个棋子的合适位置,这

八皇后之回溯法解决[转]

问题描述: 要在8*8的国际象棋棋盘中放8个皇后,使任意两个皇后都不能互相吃掉.规则是皇后能吃掉同一行.同一列.同一对角线的棋子.如下图即是两种方案: . 解决方案: 8*8的棋盘要摆放8个皇后,且不能同行同列同对角线,那么每行必定会有一个皇后.我们可以设一个数组a用来存放每一行皇后的位置,元素值表示第几列(如a[1]=5表示第一行的皇后处于第五个格).然后只需要求出数组a的值 问题就解决了,下面介绍三种回溯解法: 1.八个for循环.用枚举的办法,八个for循环分别枚举每一行的8个位置,但是我

2、八皇后问题——回溯法

/** * */ package unit1; /** * @author * @version 创建时间:2015-10-30 下午02:55:24 类说明 */ public class EightQueensNotRecursive { private static final boolean AVAILABLE = true; private int squares = 16, norm = squares - 1; private int positionInRow[] = new i

八皇后问题-回溯法(matlab)

1.问题描述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上. 2.matlab代码 function PlaceQueen(row,stack,N)%回溯法放置皇后 if row>N PrintQueen(N,stack);%打印棋盘 else for col=1:N stack(row)=col; if row==1||Conflict(row,col,N,stack)%检测是

八皇后,回溯与递归

python语句的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩展为九皇后,十皇后问题. 问题:在一个8*8棋盘上,每一行放置一个皇后旗子,且它们不冲突.冲突定义:同一列不能有两个皇后,每一个对角线也不能有两个皇后.当然,三个皇后也是不行的,四个也是不行的,应该凭智商应该可以理解吧. 解决方案:回溯法和递归法 1 import random 2 3 def conflict(state,col): 4 row=len(state)

八皇后问题-回溯法解

八皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. int g_number = 0;? //多少种摆放方法?void EightQueen(){? ?const int queens = 8;? //棋盘大小?? ?int ColumnIndex[queens];? //列索引?//遍历行? ?for(int i = 0; i < queens; ++ i)?? ? ? ?ColumnIndex[i] = i;

八皇后问题——回溯

经典八皇后问题参考博客http://blog.csdn.net/mbh_1991/article/details/23869459 下面解决八皇后的改版问题: AC代码: 1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 char board[10][10]; 6 int board2[10][10]; 7 int num=0; //记录八皇后的个数 8 int res=0; 9 int di

八皇后问题——回溯法(python&amp;&amp;JAVA)

八皇后问题,是一个古老而著名的问题,问题如下: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 上边是一个8*8的国际棋盘,可以看到棋盘中的每个格子都标有数字.每个数字都是两位,十位数字表示该格子所在的行,而个位数字表示该格子所在的列. 这样不难发现,处在同一行的两个格子其十位数都相同,处在同一列的两个格子其个位数都相同,处在同一斜线的两个格子有:|两个数字个位数的差|=|两个数字十位数的差|. 主要的三个限制条件明白了