八皇后 8! 92 ?

#include <stdio.h>  
#include <stdlib.h>  

/*--------------------八个皇后----------------------*/  
#define QUEEN_NUM 8  
int label[QUEEN_NUM][QUEEN_NUM]={
    0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,     
    0,0,0,0,0,0,0,0,       
    0,0,0,0,0,0,0,0,      
    0,0,0,0,0,0,0,0,      
    0,0,0,0,0,0,0,0,      
    0,0,0,0,0,0,0,0,      
    0,0,0,0,0,0,0,0      
    };  

void AllClear()  
{  
    for(int i=0;i<QUEEN_NUM;++i)  
        for(int j=0;j<QUEEN_NUM;++j)  
            label[i][j]=0;  

}

void PrintResult()  
{  
    for(int i=0;i<QUEEN_NUM;++i)  
    {  
        for(int j=0;j<QUEEN_NUM;++j)  
            printf("%d ",label[i][j]);  
        printf("\n");  

    } 
    printf("-------------------------------------------\n");  
}

int getColumnIndexForLine(int line)
{
    int* p_line=label[line];
    int index=0;
    while (p_line[index] ==0 && index<8)
    {
        index+=1;
    }
    if (p_line[index] ==1)
    {
        return index;
    } 
    else
    {
        return -1;
    }
}

bool CheckOK(int endLineIndex)
{
    for (int line=0;line<=endLineIndex;line++)
    {
        int cloumn=getColumnIndexForLine(line);
        if (cloumn>=0)
        {
            for (int i=0;i<=endLineIndex;i++)
            {
                if (i!=line && label[i][cloumn]==1)
                {
                    return false;
                }
            }
            
        }
        else
        {
            printf("line %d has no 1!!!\n",line);
            PrintResult();
            system("pause");
            return false;
        }
    }

    return true;
}

void main()
{
    int resultCount=0;
    int idx[8];
    for (idx[0]=0;idx[0]<8;idx[0]++)
    {
        label[0][idx[0]]=1;
        for (idx[1]=0;idx[1]<8;idx[1]++)
        {
            label[1][idx[1]]=1;
            if(!CheckOK(1)){
                label[1][idx[1]]=0;
                continue;
            }
            for (idx[2]=0;idx[2]<8;idx[2]++)
            {
                label[2][idx[2]]=1;
                if(!CheckOK(2))
                {
                    label[2][idx[2]]=0;
                    continue;
                }
                for (idx[3]=0;idx[3]<8;idx[3]++)
                {
                    label[3][idx[3]]=1;
                    if(!CheckOK(3))
                    {
                        label[3][idx[3]]=0;
                        continue;
                    }
                    for (idx[4]=0;idx[4]<8;idx[4]++)
                    {
                        label[4][idx[4]]=1;
                        if(!CheckOK(4))
                        {
                            label[4][idx[4]]=0;
                            continue;
                        }
                        for (idx[5]=0;idx[5]<8;idx[5]++)
                        {
                            label[5][idx[5]]=1;
                            if(!CheckOK(5))
                            {
                                label[5][idx[5]]=0;
                                continue;
                            }
                            for (idx[6]=0;idx[6]<8;idx[6]++)
                            {
                                label[6][idx[6]]=1;
                                if(!CheckOK(6))
                                {
                                    label[6][idx[6]]=0;
                                    continue;
                                }
                                for (idx[7]=0;idx[7]<8;idx[7]++)
                                {
                                    label[7][idx[7]]=1;
                                    //check ...
                                    if(!CheckOK(7))
                                    {
                                        label[7][idx[7]]=0;
                                        continue;
                                    } 
                                    else
                                    {
                                        resultCount+=1;
                                        PrintResult();
                                    }
                                    label[7][idx[7]]=0;
                                }
                                label[6][idx[6]]=0;
                            }
                            label[5][idx[5]]=0;
                        }
                        label[4][idx[4]]=0;
                    }
                    label[3][idx[3]]=0;
                }
                label[2][idx[2]]=0;
            }
            label[1][idx[1]]=0;
        }
        label[0][idx[0]]=0;
    }

    printf("resultCount=%d\n",resultCount);
}
//
// 8!=40320
//
#include<stdio.h>  
#include<windows.h>  
#define N 8 //可以根据N来修改棋盘的格数   
int count = 0;//设置一个计数器   
int chess[N][N] = {0};//用于存放棋盘的二维数组   

/*
整体思路:
创建一个全局变量的二维数组chess;
并初始化全为0
一行一行开始放皇后;
若存在相互攻击,则皇后向右移一列
若不存在攻击,进行下一行皇后的放置(这里要用到递归)
要点:
(1)国际象棋的格数
国际像是是8*8,因此,如果放置八个皇后,那么每一行都有一个
(2)问题具体化
利用二维数组,用1来代表皇后,其他为0
(3)皇后的放置方法
利用循环,判断位置是否可以放置皇后,若可以,则放置(将其置1)
*/


void print()//打印函数   
{     
    int i = 0;  
    int j = 0;  
    printf("*****************************************\n");  
    for(i = 0; i<N ;i++)  
    {  
        for(j = 0; j<N ; j++)  
        {  
            printf("%d ",chess[i][j]);  
        }  
        printf("\n");  
    }  
    printf("*****************************************\n");  
}

//判断是否会互吃   
//关键条件  
//返回1 表示存在互吃  
//返回0 表示正常   
int check(int i, int j)//i = 7,j = 4   
{     
    if(i == 0)  
        return 0;//表示正常  

    int k = 0;  
    for(k = 0; k<i ; k++)  
    {  
        if(chess[k][j] == 1)//(0,4)(1,4)...  
            return 1;  
    }  
    for( int s = 0,k = j+1; k<N ;k++)  
    {     
        //(7,4)(6,5),(5,6),(4,7)  
        if(chess[i-s-1][k] == 1)//(0,11),(1,10),(2,9),(3,8),(4,7)  
            return 1;  
        s++;  
    }  
    for(k = 0; k<j ;k++)  
    {  
        if(chess[i-k-1][j-k-1] == 1)//(6,3)(5,2)(4,1)(3,0)
            return 1;     
    }  
    for(k = 0; k<N ; k++)  
    {  
        if(chess[k][j]==1)  
            return 1;  
    }  
    return 0;  
}

//判断棋盘上是否有一行存在没有皇后的情况   
//返回0 ,表示棋盘正常(每一行都有皇后)  
//返回1 ,表示棋盘有错   
int check_all()  
{  
    int i = 0;  
    int j = 0;  
    int flag = 0;  
    for(i = 0; i<N ;i++)  
    {     
        flag = 0;  
        for(j = 0; j<N ; j++)  
        {  
            if(chess[i][j]==1)  
            {  
                flag = 1;  
                break;  
            }  
        }  
        if(flag == 0)  
            return 1;//有错   
    }  
    return 0;  
}

//检查某一行是否存在皇后  
//返回0 表示存在  
//返回1 表示没皇后   
int check_line(int line)  
{     
    if(line==0)  
        return 0;  
    int k = 0;  
    int s = 0;  
    int flag = 1;  
    for(s = 0; s<line-1 ; s++)  
    {     
        flag = 1;  
        for(k = 0; k<N ;k++)  
        {  
            if(chess[s][k]==1)  
                flag = 0;  
        }  
        if(flag==1)  
            return 1;  
    }  
    return 0;  
}

//递归的主要算法   
void queen(int i,int j)  
{         
    //符合,置一,进入下一行  
    if(check_line(i)==1)//若该行有皇后,返回   
        return ;  
    if((i==(N-1)))//若此时是最后一行   
    {         
        if(check(i,j)==0)//当最后一行的皇后可以放下(表示可以成功放置)     
        {  
            chess[i][j] = 1;//将该位置1,表示皇后   
            print();//打印   
            count++;//计数器+1   
        }  
    }         
    if(check(i,j)==0)//当可以放皇后时   
    {     
        chess[i][j] = 1;//放入   
        //print();  
        //Sleep(1000);  
        queen(i+1,0);//进行下一行的皇后放置   
    }  
    if(j==N)//如果j等于列数,表明越界,返回   
        return ;  

    chess[i][j] = 0;//将该位置0   
    //print();  
    //Sleep(500);  
    //不符合,置零,右诺  
    queen(i,j+1);//将该行皇后右移一位   
}

int main(void)  
{     
    queen(0,0);  
    printf("\ncount = %d\n",count);  
    return 0;  
}
//count = 95
//--------------------------------------  
//利用函数递归,解决八皇后问题  
//  
//  zssure  2014-03-12  
//--------------------------------------  
/*
思路分析
其实该问题并不难,利用递归方法很容易解决。
没放置一个皇后,就将其能够攻击的区域进行标记,
然后放置下一个皇后,一次类推……;
此外,如果有解最终肯定是每一行有且只有一位皇后,
所以放置的时候按照逐行放置的顺序进行。
此问题难点在于如何把控递归函数的返回条件,
一种条件是8个皇后放置完成后,返回成功,
一种条件是该行中已经没有可以放置的位置,
此时返回失败,需要重新放置。此时要额外注意,
所谓的“重新放置”指的并不是将所有皇后清除重新来过,
而是只返回上一层,将上一个导致本次放置失败的皇后进行清除,
然后重新更新其位置,通过逐级放置、
或逐级回溯可以达到遍历所有情况找到所有解
(下文中给出的自己的代码的计算结果不是独立解的个数,
而是所有可行解的情况)
*/  
#include <stdio.h>  
#include <cmath>  
  
int count=0;//全局计数变量  
  
/*--------------------四个皇后----------------------*/  
//#define QUEEN_NUM 4  
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,      
//                                  0,0,0,0,  
//                                  0,0,0,0,  
//                                  0,0,0,0 };  
  
/*--------------------五个皇后----------------------*/  
//#define QUEEN_NUM 5  
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,0,  
//                                  0,0,0,0,0,  
//                                  0,0,0,0,0,  
//                                  0,0,0,0,0,  
//                                  0,0,0,0,0       };  
  
/*--------------------六个皇后----------------------*/  
//#define QUEEN_NUM 6  
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,  
//                                  0,0,0,0,0,0  
//                                                  };  
  
/*--------------------七个皇后----------------------*/  
//#define QUEEN_NUM 7  
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,0,  
//                                  0,0,0,0,0,0,0  
//                                                  };  
  
/*--------------------八个皇后----------------------*/  
#define QUEEN_NUM 8  
int label[QUEEN_NUM][QUEEN_NUM]={0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0,  
                                 0,0,0,0};  
  
  
void FillChessbox(int m,int n,int num)  
{  
    for(int i=0;i<QUEEN_NUM;++i)  
        for(int j=0;j<QUEEN_NUM;++j)  
            if(abs(i-m)==abs(j-n))//对角区域填充  
            {  
                if(label[i][j]==0)  
                    label[i][j]=num;  
            }  
  
    int i=0,j=0;  
    while(i<QUEEN_NUM)//行填充  
    {  
        if(label[i][n]==0)  
            label[i][n]=num;  
        ++i;  
    }  
    while(j<QUEEN_NUM)//列填充  
    {  
        if(label[m][j]==0)    
            label[m][j]=num;  
        ++j;  
    }  
  
}

void ClearChessBox(int m,int n,int num)  
{  
    for(int i=0;i<QUEEN_NUM;++i)  
        for(int j=0;j<QUEEN_NUM;++j)  
            if(abs(i-m)==abs(j-n) && label[i][j]==num)  
                label[i][j]=0;  
    int i=0,j=0;  
    while(i<QUEEN_NUM)  
    {  
        if(label[i][n]==num)  
            label[i][n]=0;  
        ++i;  
    }  
    while(j<QUEEN_NUM)  
    {  
        if(label[m][j]==num)  
            label[m][j]=0;  
        ++j;  
    }  
}

void AllClear()  
{  
    for(int i=0;i<QUEEN_NUM;++i)  
        for(int j=0;j<QUEEN_NUM;++j)  
            label[i][j]=0;  
  
}

void PrintResult()  
{  
    for(int i=0;i<QUEEN_NUM;++i)  
    {  
        for(int j=0;j<QUEEN_NUM;++j)  
            printf("%d ",label[i][j]);  
        printf("\n");  
                  
    }  
}

bool EightQueen(int n/*皇后个数*/,int c/*已经放置的皇后个数*/)  
{  
    //static int count=0;  
    //小于3x3的棋盘是无解的  
    if(n<4)  
        return false;  
  
    for(int i=0;i<n;++i)  
    {  
        if(label[c-1][i]==0)//存在可以放置第c个皇后的位置  
        {  
            label[c-1][i]=c+1;  
            if(c==n)/*已经放置完毕所有的皇后*/  
            {  
                ++count;  
                PrintResult();  
                printf("**************************\n");  
                ClearChessBox(c-1,i,c+1);  
                //AllClear();  
                return true;  
            }  
            FillChessbox(c-1,i,c+1);  
            EightQueen(n,c+1);  
            ClearChessBox(c-1,i,c+1);  
            /*------------------------------------------------------------------------------------------------------------------------- 
            //  现场恢复,无论下一个皇后是否顺利放置,都应该恢复现场。原因是 
            // 
            //  如果下一个皇后放置失败,那么自然应该将本次放置的皇后去除,重新放置,所以需要进行现场恢复(即回溯); 
            //  如果下一个皇后放置成功,意味着本次放置已经满足条件,是一个解,此时需要恢复现场,进行下一次的重新放置,寻找下一个解。 
            // 
            //------------------------------------------------------------------------------------------------------------------------*/  
            //if(!EightQueen(n,c+1))  
            //  ClearChessBox(c-1,i,c+1);  
  
        }  
    }  
    return false;  
}
  
int main()  
{  
    EightQueen(QUEEN_NUM,1);  
    printf("%d\n",count);  
    return 0;  
}

//92

 

posted @ 2018-02-05 10:49  sky20080101  阅读(78)  评论(0)    收藏  举报