n皇后问题-c语言实现

n皇后问题描述为:在一个nxn的棋盘上摆放n个皇后,要求任意两个皇后不能冲突,即任意两个皇后不在同一行、同一列或者同一斜线上。

 

1,1

1,2

1,3

1,4

2,1

2,2

2,3

2,4

3,1

3,2

3,3

3,4

4,1

4,2

4,3

4,4

上面是4皇后摆放方案,只有两种

寻找皇后摆放方案,可采用回溯法设计策略

算法的基本思想如下:

将第个皇后摆放在第行,从1开始,每个皇后都从第1列开始尝试。尝试时判断在该列摆放皇后是否与前面的皇后有冲突,如果没有冲突,则在该列摆放皇后,并考虑摆放下一个皇后;如果有冲突,则考虑下一列。如果该行没有合适的位置,回溯到上一个皇后,考虑在原来位置的下一个位置上继续尝试摆放皇后,直到找到所有合理摆放方案。

核心代码问题是:如何判断某行某列的位置是否有冲突,即是否有任意两个皇后在同一行、同一列或者同一斜线上

判断是否在同一列上非常好判断,列号相同即为在同一列

是否在同一行没必要判断,因为他是一行一行深度优先遍历的

判断是否处于同一右斜线,由下图可以总结规律两位置的行号加上列号相等,如1+4=2+3

判断是否处于同一左斜线,由下图可以总结规律两位置的行号减上列号相等,如2-1=3-2

n皇后问题-c语言实现_第1张图片

queen[i]+i=queen[j]+j和queen[i]-i=queen[j]-j  ===>  queen[i]- queen[j]= j-i和queen[i]- queen[j]= -(j-i)  ====>  abs(queen[i]- queen[j]) = j-i

#include 

#define N 4  //N代表皇后个数
int queen[N+1];  //表示皇后所在的位置,如queen[1]=2表示皇后在第一行第二列
int count = 0;

void show(){
    printf("(");
    for (int i = 1; i <= N; i++)
    {
        printf("%d ", queen[i]);
    }
    printf(")\n");
}

int isQueen(int j){  //判断该列能否放置皇后,能放返回1,不能返回0
    int i;
    for (i = 1; i < j; i++){   //检查已经摆放好的皇后是否在同一列上或者在同一斜线上
        if(queen[i] == queen[j] || abs(queen[i]-queen[j]) == j-i){
            return 0;
        }
    }
    return 1;
}

/**
 * @brief 
 * 
 * @param j 行数,递归时用到
 * i为列数
 */
void Nqueen(int j){
    int i;
    for (i = 1; i <= N; i++)  //遍历行,即遍历所有方案,找出可行方案
    {
        queen[j] = i;
        if(isQueen(j)){  //判断该列能否放置皇后
            if(j == N){  //所有皇后拜访好了,输出摆放方案
            count ++;
                show();
            }else{
                Nqueen(j+1);  //递归,摆放下一个皇后
            }
        }
    }
}


int main(void){
    Nqueen(1);
    printf("方案数:%d", count);
    return 0;
}

 

你可能感兴趣的:(算法,算法,c语言)