n皇后问题

问题描述:
n皇后问题是一个古老而著名的问题,由国际象棋
棋手马克斯·贝瑟尔于1848年提出:在n×n格的国际象棋上摆放
n个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同
一行、同一列或同一斜线上,问有多少种摆法?一种摆法称为问
题的一个解
回溯法思想:
第一个棋子从第一行开始,按照列从小到大的顺序选择摆放的位
置;接下来从第二行按照可行的方案,从小到大的顺序摆放第二个棋
子;在第一和第二个棋子固定的情况下,再选择可行的位置在第三行
上摆放第三个棋子,以此类推。每一步的执行将使问题变成更小规模
的问题而向下递归。
如果在某一行没有找到不冲突位置,则需要 回溯到上一行 ,以此
类推,直至找出全部正确解。
非递归回溯算法的实现:
void Queens(int n) //求解n皇后问题
{ int i=1; //i表示当前行,也表示放置第i个皇后
q[i]=0; //q[i]是当前列,每个新考虑的皇后初始位置置为0列
while (i>=1) //尚未回溯到头,循环
{ q[i]++; //原位置后移动一列
while (q[i]<=n && !place(i)) //试探一个位置(i,q[i])
q[i]++;
if (q[i]<=n) //为第i个皇后找到了一个合适位置(i,q[i])
{ if (i==n) //若放置了所有皇后,输出一个解
dispasolution(n);
else //皇后没有放置完
{ i++; //转向下一行,即开始下一个新皇后的放置
q[i]=0; //每个新考虑的皇后初始位置置为0列
}
}
else i--; //若第i个皇后找不到合适的位置,则回溯到上一个皇后
}
}
bool place(int i) //测试第i行的q[i]列上能否摆放皇后
{ int j=1;
if (i==1) return true;
while (j<i) //j=1~i-1是已放置了皇后的行
{ if ((q[j]==q[i]) || (abs(q[j]-q[i])==abs(j-i)))
//该皇后是否与以前皇后同列,位置(j,q[j])与(i,q[i])是否同对角线
return false;
j++;
}
return true;
}
5.3.2 n皇后问题
5.3.2

非递归回溯算法的实现:
void Queens(int n)
// 求解 n 皇后问题
{ int i=1;
//i 表示当前行 , 也表示放置第 i 个皇后
q[i]=0;
//q[i] 是当前列 , 每个新考虑的皇后初始位置置为 0
while (i>=1)
// 尚未回溯到头,循环
{ q[i]++;
// 原位置后移动一列
while (q[i]<=n && ! place (i)) // 试探一个位置 (i,q[i])
q[i]++;
if (q[i]<=n)
// 为第 i 个皇后找到了一个合适位置 (i,q[i])
{ if (i==n)
// 若放置了所有皇后 , 输出一个解
dispasolution(n);
else
// 皇后没有放置完
{ i++;
// 转向下一行 , 即开始下一个新皇后的放置
q[i]=0;
// 每个新考虑的皇后初始位置置为 0
}
}
else i--;
// 若第 i 个皇后找不到合适的位置 , 则回溯到上一个皇后
}
}
bool place(int i)
// 测试第 i 行的 q[i] 列上能否摆放皇后
{ int j=1;
if (i==1) return true;
while (j<i)
//j=1 i-1 是已放置了皇后的行
{ if ((q[j]==q[i]) || (abs(q[j]-q[i])==abs(j-i)))
// 该皇后是否与以前皇后同列,位置 (j,q[j]) (i,q[i]) 是否同对角线
return false;
j++;
}
return true;
}
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值