经典八皇后

题目描述:

  在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法!

 

这道题,很明显的回溯法

回溯法的的精髓说白了就是要有一个状态标志,然后根据这标志来决定,下一步走不走.

这里这个标志我们选用一个n*n的二维数组

#include"iostream"
using namespace std;
int a[100][100],ans;
const int n=8;
int check(int x,int y){
//检查当前皇后的位置(x,y)与其他皇后有冲突吗
// printf("正在检查%d行,%d列\n",x,y); int i,j; for(i=1;i<=n;i++) if(a[i][y]==1)//判断同行同列有没有皇后 return 0; //判断对角线 for(i=x,j=y;i>=1&&j>=1;i--,j--)//当前位置的左上, if(a[i][j]==1) return 0; for(i=x,j=y;i>=1&&j<=n;i--,j++)//右上位置 if(a[i][j]==1) return 0; return 1; } void print(){ int i,j; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) cout<<a[i][j]<<" "; cout<<endl; } cout<<endl; } void dfs(int row){ // cout<<"行:"<<row<<endl; int i; if(row>n){//递归结束,进行结果的输出 ans++;//解的个数 print(); return ; } for(i=1;i<=n;i++){ //检查 if(check(row,i)){//检查当前位置可用不可用 // printf("第%d行,%d列可以用\n",row,i); a[row][i] = 1;//标记第row行第i列 dfs(row+1);//进入下一行 a[row][i] = 0; //这一步是最关键的一步,状态回溯,将之前的标志取消 } } } int main(){ cout<<"开始执行--------"<<endl; dfs(1); cout<<ans<<endl; }

 2020年5月1日21:22:55增加:

可以对标志数组进行压缩,压缩成一维数组

#include<iostream>
using namespace std;

int a[10],count;
const int n =8;

void print(){
      for (int i = 0; i <= n; i++)
    {   
        int inner;
        for (inner = 1; inner <= a[i]; inner++)
            cout << "0 ";
            cout <<"K ";
        for (inner = a[i] + 1; inner <= n; inner++)
            cout << "0 ";
        cout << endl;
    }
    cout << "==========================\n";
}
int check(int index,int loop){
    int data,index_pre;
    //index loop表示当前第index个皇后所在列为loop
    //data index_pre表示前index个皇后所在列为data
    for(index_pre=1;index_pre<index;index_pre++){
        //data表示前面皇后所在的列,index_pre表示前面的第index_pre个皇后
        data = a[index_pre];
        //判断是否在同一列 
        if(loop==data){
            return 0;
        }
        //判断当前皇后的右上角//右下角 (1,3)和(0,4) 3+1==0+4 
        if((index+loop)==(index_pre+data))
            return 0;
        
        //判断当前皇后的左下角 (1,3)和(2,4) 3-1==4-2 
        if((loop-index)==(data-index_pre))
            return 0;                 
    } 
    return 1;
}
void eightQueue(int index){
    for(int loop=1;loop<=n;loop++){
        if(check(index,loop)){
            a[index] = loop;
            if(index==n){
                count++;
                print();            
                a[index] = 0;//回溯
                return;
            }
            eightQueue(index+1);
            a[index] = 0; //回溯
        }
    }
}

int main(){
    eightQueue(1);
    cout<<"总计:"<<count<<endl; 
} 

 

posted @ 2020-05-01 17:47  TiSou1  阅读(181)  评论(0)    收藏  举报