免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1428 | 回复: 0
打印 上一主题 下一主题

n皇后问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-28 23:51 |只看该作者 |倒序浏览
在n行n列的棋盘上,如果两个皇后位于棋盘上的同一行或者同一列或者同一对角线上,则称他们为互相攻击。现要求找出使n元棋盘上的n个皇后互不攻击的所有布局。
采用回溯算法,搜索整个解空间。求出所有解。
递归回溯
C语言风格
#include iostream>
using namespace std;
long sum=0;
bool Place(int k,int *p){//判断是否有冲突发生。k是当前摆放行
    for(int j=0;jk;j++)//p[j]==p[k]说明第j行与第k行放在同一列
        if(abs(k-j)==abs(p[j]-p[k])||p[j]==p[k])
        //abs(k-j)==abs(p[j]-p[k])说明斜率为+-1,说明在同一列
            return false;
    return true;
}

void Backtrack(int t,int *p,int n){
    if(t>=n)//棋盘共有n行,用0~n-1表示,故如果t到达n,递归返回
        sum++;//增加一次成功次数
    else
        for(int i=0;in;i++){//对第t行进行摆放尝试,可能情况是0~n-1
            p[t]=i;
            if(Place(t,p))Backtrack(t+1, p,n);//如果无冲突,摆放t+1行
        }
}
int nQueen(int n){
    int *p=new int[n];//数组p表示棋盘第i行皇后的位置
    for(int i=0; in;i++)
        p=0;//将棋盘数组初始化为0;
    Backtrack(0, p, n);//回溯求解,从第0行开始摆放
    delete [] p;
    return sum;
}
int main(){
    coutnQueen(8);
    return 0;
}

C++风格

#include
using namespace std;
class Queen{
    friend int nQueen(int);//执行函数
private:
    bool Place(int k);//测试第k行摆放后,是否有冲突发生
    void Backtrack(int t);//回溯
    int n,*x;//n为棋盘行数,x为记录每行的摆放位置的数组
    long sum;//记录成功次数
};
bool Queen::Place(int k){//同上
    for(int j=0;jk;j++)
        if(abs(k-j)==abs(x[j]-x[k])||x[j]==x[k])
            return false;
    return true;
}
void Queen::Backtrack(int t){//同上
    if(t>=n)
        sum++;
    else
        for(int i=0;in;i++){
            x[t]=i;
            if(Place(t))Backtrack(t+1);
        }
}
int nQueen(int n){
    Queen X;
    X.n = n;//棋盘行数
    X.sum = 0;//成功次数
    int *p=new int[n];
    for(int i=0; in;i++)
        p=0;
    X.x=p;
    X.Backtrack(0);//回溯
    delete [] p;
    return X.sum;
}
int main(){
    coutnQueen(8);
    return 0;
}

迭代回溯:
c语言风格
#include iostream>
using namespace std;
long sum=0;
bool Place(int k,int *p){//同上
    for(int j=0;jk;j++)
        if(abs(k-j)==abs(p[j]-p[k])||p[j]==p[k])
            return false;
    return true;
}
void Backtrack(int *p,int n){
    p[0] = -1;
    int i = 0;
    while(i>=0){
        p++;
        while(pn&&!(Place(i, p))) p++;
        if(pn){
            if(i == n-1) sum++;
            else{
                i++;
                p = -1;
            }
        }else
            i--;
    }
}
int nQueen(int n){
    int *p=new int[n];
    for(int i=0; in;i++)
        p=0;
    Backtrack(p, n);
    delete [] p;
    return sum;
}
int main(){
    coutnQueen(8);
    return 0;
}
迭代回溯
c++风格
#include iostream>
using namespace std;
class Queen{
    friend int nQueen(int);//执行函数
private:
    bool Place(int k);//测试第k行摆放后,是否有冲突发生
    void Backtrack(int t);//回溯
    int n,*x;//n为棋盘行数,x为记录每行的摆放位置的数组
    long sum;//记录成功次数
};
bool Queen::Place(int k){//同上
    for(int j=0;jk;j++)
        if(abs(k-j)==abs(x[j]-x[k])||x[j]==x[k])
            return false;
    return true;
}
void Queen::Backtrack(int t){//同上
    int i=0;//从第0行开始摆放
    x=-1;//初始化,x取值范围是0~n-1
    while(i>=0){//回溯初始行为0;
        x++;//从第0个位置摆放第i行
        while(xn&&!Place(i)) x++;//找到下一个没冲突的位置
        if(xn){//找到了没有冲突的位置
            if(i == n-1) sum++;//摆放结束
            else{//摆放下一行
                i++;
                x=-1;
            }
        }else//找完了整行,没有找到合适的位置,则回到上一行
            i--;//找上一行合适的位置,
    }
}
int nQueen(int n){
    Queen X;
    X.n = n;//棋盘行数
    X.sum = 0;//成功次数
    int *p=new int[n];
    for(int i=0; in;i++)
        p=0;
    X.x=p;
    X.Backtrack(0);//回溯
    delete [] p;
    return X.sum;
}
int main(){
    coutnQueen(8);
    return 0;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/70469/showart_1270307.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP