我正在解决N皇后问题,我们需要在N X N棋盘上放置N个皇后,这样就不会有两个皇后可以相互攻击。
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int size=8;
char arr[8][8];
int i,j;
void initializeBoard()
{
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
arr[i][j]='.';
}
}
}
void printArray()
{
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
printf("%c\t",arr[i][j]);
}
printf("\n");
}
printf("\n\n");
}
void placeQueen(int i,int j)
{
arr[i][j]='Q';
}
int isAvailable(int i,int j)
{
int m,n,flag;
for(m=0;m<i;m++)
{
for(n=0;n<size;n++)
{
int k=abs(i-m);
int l=abs(j-n);
if(arr[m][j]!='Q' && arr[k][l]!='Q')
{
flag=1;
}
else
{
flag=0;
break;
}
}
}
return flag;
}
int main(void)
{
initializeBoard();
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
if(isAvailable(i,j)==1)
{
// means that particular position is available
// and so we place the queen there
placeQueen(i,j);
break;
}
}
}
printArray();
return 0;
}
我认为问题出在isAvailable()方法上。但是,我无法找到错误。请帮我识别一下。
我采取的方法是否涉及回溯?如果没有,请提供相同的解释
答案 0 :(得分:1)
之前完成此问题,并非所有展示位置都允许有效解决问题。
您的解决方案涉及始终将女王放置在始终可用的位置(0,0)。
当你经历一切并且找不到任何东西时,你将需要涉及回溯,或者你需要依赖一个解决方案,将所有女王随机放置并检查解决方案(这种方法实际上比你会想,但同时,随机因此在一般情况下非常低效)
潜在的伪解决方案:
while(!AllQueensPlaced){
for(going through the array ){
if(isAvailable())
{
placeQueen();
lastQueenPlaced = some logical location of last queen;
}
}
if(!AllQueensPlaced)
{
backtrack(lastQueenPlaced);
}
}
你的回溯方法应该将lastQueenPlaced标记为脏并再次遍历数组寻找新位置,然后再次执行while循环。不要忘记在backtrack()中更改lastQueenPlaced,以防它也是lastQueenPlaced。
答案 1 :(得分:1)
您的方法不会回溯。它迭代了一些可能性,而不是全部。这个问题最好以递归的方式解决,所以我不会像你那样做。你必须为女王被其他人攻击的规则定义。您可以使用ifs
和递归来再次应用规则并进行迭代。大多数回溯算法都是递归写入的。
我会给你一个答案,所以你可以根据我的答案。
#include <stdio.h>
#include <stdlib.h>
int count = 0;
void solve(int n, int col, int *hist)
{
int i, j;
if (col == n) {
printf("\nNo. %d\n-----\n", ++count);
for (i = 0; i < n; i++, putchar('\n'))
for (j = 0; j < n; j++)
putchar(j == hist[i] ? 'Q' : ((i + j) & 1) ? ' ' : '.');
return;
}
# define attack(i, j) (hist[j] == i || abs(hist[j] - i) == col - j)
for (int i = 0, j = 0; i < n; i++) {
for (j = 0; j < col && !attack(i, j); j++);
if (j < col) continue;
hist[col] = i;
solve(n, col + 1, hist);
}
}
int main(int n, char **argv)
{
if (n <= 1 || (n = atoi(argv[1])) <= 0) n = 8;
int hist[n];
solve(n, 0, hist);
}
回溯的方式如下:
n
,即电路板的大小。搜索的最佳方式是递归,因此请记住,解决的智能方法是使用递归。 for
循环只打印出来,并检查Q
是否找到。# define attack(i, j) (hist[j] == i || abs(hist[j] - i) == col - j)
是我的规则,断言2个皇后不互相攻击。for
循环在约束规则中找到可以插入另一个女王的条件。f(n+1) = f(n) + 1
针对该案例而f(2) = 2
是我的基本案例。 答案 2 :(得分:0)
使用单维数组来跟踪每行中可放置后置的列。
可以将女王受到威胁的条件定为 1)ColumnForRow [i] == ColumnForRow [j] - 它们将在同一列中 2)(ColumnForRow [i] - ColumnForRow [j])==(i-j)或 (ColumnForRow [j] - ColumnForRow [i])==(i - j) - 它们将在同一对角线上。公共课NQueenSolver {
static int BOARD_SIZE = 15;
static int count = 0;
static int columnForRow[] = new int[BOARD_SIZE];
public static void main(String[] args) {
PlaceQueen(0);
System.out.println(count);
}
static boolean check(int row) {
for (int i = 0; i < row; i++) {
int diff = Math.abs(columnForRow[i] - columnForRow[row]);
if (diff == 0 || diff == row - i)
return false;
}
return true;
}
static void PlaceQueen(int row) {
if (row == BOARD_SIZE) {
printBoard();
++count;
return;
}
for (int i = 0; i < BOARD_SIZE; i++) {
columnForRow[row] = i;
if (check(row)) {
PlaceQueen(row + 1);
}
}
}
private static void printBoard() {
//System.out.println(Arrays.toString(columnForRow));
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
if (columnForRow[i] == j)
System.out.print("Q ");
else
System.out.print("* ");
}
System.out.println();
}
System.out.println();
}
}
答案 3 :(得分:0)
你的代码没有递归方法,这是在设计回溯算法时应首先考虑的问题。因此,您没有在此实施任何回溯策略。
你的函数isAvailable()在很多方面都不完整。
要检查已放置的皇后是否有单元格(行,列)受到攻击,您可以使用以下策略。
逐行放置女王
要将女王放在第i行,我们需要检查与放置在0到第(i-1)行的女王的冲突。
女王水平,垂直和对角线攻击。
boolean isSafe = true;
for(int queen = 0; queen<row; queen++) // Checking with already placed queens
{
// attack condition
if(position[queen].column == column || position[queen].row +
position[queen].column == row + column || position[queen].row -
position[queen].column == row-column)
{
isSafe = false;
break;
}
}
希望这有帮助。