C递归的N皇后问题.

前几天,突然有朋友要让解决八皇后问题,当时听了真有些刷刷流汗的感觉,因为许久不弄算法了,这是其一,而且当时上大一时对八皇后问题很感兴趣,但当时能力所限,弄了一周也没有求出全解.后来虽然理论知识充分了,但也已经没有时间去研究.

拿着VS一边流汗一边CODE,记着当前说这个东西要用分治和递归来解决,用了半小时,嘿,还真写出来了,呵呵,看来有压力的话还是有些作用的.

贴上来,分享一下:欢迎拍砖:

注:用的是递归+分治

/*
 * N皇后问题
 * 因为在一张N*N的棋盘上,只放N个棋子,
 * 且显然,同一行上,只会放一个(否则就
 * 会被同行的吃掉),故用一个N维数组来
 * 存储这N个棋子的信息,其中若
 *    N[i] = j
 * 表示在棋盘上第i行第j列放有一个棋子
 */
int count = 0;//用于对结果集的计数


/*输出N皇后问题的解
 *输入:
 *a[]
 *保存棋子信息的数组.
 *length
 *数组的长度,对应于N
 */
void output (int a[],int length){
 int i ,j;
 count ++;
 printf("The %d of the solution is :/n",count);
 for(int i =0;i<length;i++){
  for(int j= 0;j<length;j++)
   printf("%d",a[i]==j?1:0);
  printf("/n");
 }
}

/* 往棋盘上放棋子的递归算法
 * 输入:
 * a
 * 存储棋子位置的数组
 * length
 * 数组的长度
 * off
 * 要放置第几个棋子,从0开始计数
 */
void check(int a[],int length,int off){
 int i = 0; //循环计数器
 int value;  //要放置的值

 /*如果off和长度相等,说明棋子已经全放好了,只要将其输出即可*/
 if(off == length){
   output(a,length);
  return;
 }

 /* 从0value到length表示依次在棋盘的第off行,第value列上放置棋子*/
 for(value = 0;value<length;value++){

  /*放置后对已放置的棋子进行校验*/
  for(i = 0;i<off;i++)
   if(value - a[i] == 0  //value-a[i]=0表示同一列上有两个棋子  
    ||value - a[i]== off - i//value-a[i]= off -i表明同一左斜线上有两个棋子
    ||value - a[i]== i-off) //value-a[i]= i - off表明同一右斜线上有两个棋子
    break;//如果不合条件则跳出循环
  if(i == off){//i == off说明校验完毕且棋子放置的位置是正确的
   a[off] = value;//将棋子放入
   check(a,length,off+1);//继续放下一个
  }
 }
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
n皇后问题是一个经典的问题,目标是在一个n×n的棋盘上放置n个皇后,使得每个皇后都不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。下面是两个C语言递归实现n皇后问题的代码: 引用: ```c #include<stdio.h> #define MAX 10 #define n 4 //4个皇后 int a[MAX];//第i个皇后在a[i]上 int sum = 0; int detection(int x,int y) {//判断是否能放 for (int i = 1; i <= x; i++) { if (a[i] == y)return 0;//|有皇后 if (i + a[i] == x + y)return 0;//斜边右边有皇后 if (i - a[i] == x - y)return 0;//斜边左边有皇后 } return 1;//可以放皇后 } void queen(int row) {//第row个皇后在? if (row == n + 1) { sum++;//完成了一组解答 printf("解法%d:",sum); for (int k = 1; k < n; k++) { printf("%d", a[k]); } printf("\n"); return; } for (int i = 1; i <= n; i++) { if (detection(row, i)) { a[row] = i; queen(row + 1); a[row] = 0;//回溯 } } } int main() { queen(1); printf("有%d种解法\n", sum); return 0; } ``` 引用: ```c #include<iostream> using namespace std; #define max 5 void dis(int chess[max][max],int n) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) cout << chess[i][j] << " "; cout << endl; } cout << endl; } bool place(int chess[max][max],int n, int x, int y) { if (x == 0) return true; else { for (int i = 0; i < x; i++) { for (int j = 0; j < n; j++) { if (chess[i][j] == 1) { if (j == y || abs(i - x) == abs(j - y)) return false; } } } } return true; } void queen(int chess[max][max],int n,int i) { if (i == n) dis(chess, n); for (int j = 0; j < n; j++) { if (place(chess, n, i, j)) { chess[i][j] = 1; queen(chess, n, i + 1); chess[i][j] = 0; } } } int main() { int chess[max][max]; memset(chess, 0, sizeof(chess)); queen(chess, max, 0); return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值