八皇后问题-回溯法

8皇后问题:
在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
因为不能同行同列,所以每行、每列有且仅有一个棋,思路如下:
逐个象棋摆放,第i个象棋摆放在第i行,摆放每个象棋时,从第一列开始,尝试放入,一旦满足放入条件便放入该象棋,然后再放下一个象棋,如果无法放入,则回到第i-1个象棋,从新摆放第i-1个象棋,如果第i-1个象棋重新摆放不了,则进一步回到第i-2个象棋,依次类推,直到可以重新摆放为止,然后再从重新摆放的象棋的下一个象棋开始继续摆放。一般地,n*n格棋盘,n个皇后,数组array[i]表示第i个皇后的列位置,因为第i个皇后一定在第i行。
C实现:

#include<stdio.h>

#include<math.h>

//考察皇后k放置在array[k]列是否发生冲突,数组下标从1开始算,因为数组第0个元素不可修改,原因略

//返回0表示冲突,返回1表示皇后K可以放在array[k]列

int  place( int  * array, int  k){

     int  i;

     for (i=1;i<k;i++){

         //判断是否同列或同一斜线

         if (array[k]==array[i]|| abs (k-i)== abs (array[k]-array[i]))

             return  0;

     }

     return  1;

}

void  main(){

     int  n = 8;

     int  * array = ( int  *) malloc ((n+1)* sizeof ( int ));

     int  i;

     for (i = 1;i<=n;i++)

         array[i] = 0; //初始化

     int  k = 1;

     //如果第1个皇后不能重新放,则程序结束,因为不能再向前回溯了

     while (k>=1){

         array[k] = array[k]+1;

         while (array[k]<=n&&place(array,k)==0)

             array[k] = array[k]+1;

         if (array[k]<=n&&k==n){

             //得到一个摆放结果

             for (i = 1;i<=n;i++)

                 printf ( "%d," ,array[i]);

             printf ( "\n" );

//          return;//若返回则只输出一种结果,否则可以继续回溯,输出所有的结果

         }

         else  if (array[k]<=n&&k<n)

             k++; //摆放下一个皇后

         else {

             //回溯

             array[k] = 0;

             k--;

         }

     }

}

Java实现:

public class Test {
    public static boolean isPlace(int[]array,int k){
        for(int i = 0;i<k;i++){
            if(array[i]==array[k]||(k-i)==Math.abs(array[k]-array[i]))
                return false;
        }
        return true;
    }
    public static void main(String[] args){
        int queen = 8;
        int array[] = new int[queen];
        int cur = 0;
        while(cur>=0){
            array[cur]++;
            if(array[cur]>queen){
                array[cur] = 0;
                cur--;
                continue;
            }
            if(isPlace(array, cur)){
                if(cur<queen-1)
                    cur++;
                else{
                    System.out.print("[");
                    for(int i = 0;i<queen-1;i++){
                        System.out.print(array[i]+",");
                    }
                    System.out.println(array[queen-1]+"]");
                }
            }
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值