Python用迭代(yield)和递归解决八皇后问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python用迭代(yield)和递归解决八皇后问题相关的知识,希望对你有一定的参考价值。

参考技术A
国际象棋的皇后行走具有最高的灵活性,可以横、竖、斜共八个方向无限步行走。你需要将国际象棋8个皇后放在棋盘上,条件是任何一个皇后都不能威胁其他皇后,即任何两个皇后都不能吃掉对方。

分析:在棋盘的第一行尝试为第一个皇后选择一个位置,再在第二行尝试为第二个皇后选择一个位置,依次类推。在发现无法为一个皇后选择合适的位置后,回溯到前一个皇后,并尝试为它选择另一个位置。当八个皇后都放在棋盘上时即得到一种解。


用元组(其他序列也可以)表示可能的解(或一部分),例如(1,3,5)表示当前共摆放了三个皇后,第一个皇后在1行1列,第二个皇后在2行3列,第三个皇后在3行5列。



当前状态state,下一个皇后在下一行的next_x位置,根据皇后的行走规则,如果已有的皇后可以吃掉下一个皇后,则表示有冲突,否则没有。

函数conflict定义:接受用状态元组表示的既有皇后的位置,并确定下一个皇后的位置是否会导致冲突。


参数 next_x 表示下一个皇后的水平位置(x 坐标,即列),而 next_y 为下一个皇后的垂直位置(y 坐标,即行)。这个函数对既有的每个皇后执行简单的检查:如果下一个皇后与当前皇后的 x 坐标相同或在同一条对角线上,将发生冲突,因此返回True ;如果没有发生冲突,就返回False 。

abs(state[i] - next_x) in (0, next_y - i) 表示两个皇后的水平距离为0或等于垂直距离时为真、否则为假。




算法入门经典-第七章 例题7-2 八皇后问题

原本利用回溯思想解决的经典八皇后问题,其实也是可以用递归解决的~

八皇后的递归解决思路:

从第一行开始,依次判断0~8列的哪一列可以放置Queen,这样就确定了该行的Queen的位置,然后行数递增,继而递归实现下一行的判断,依次类推直到行数增加到8(行数从0开始的),此时为递归-----归的条件,即表示一种八皇后的解决方法完成,打印结果;之后进行下一种解决方法的寻找,大致思路个人理解是这样

noDanger(row,j,(*chess)[8])函数是判断第row行第j列是否可以放置Queen

 

 

#include<stdio.h>
int count=0;
//参数row:起始行
//参数n:表示列数
//参数(*chess)[8]表示指向棋盘每一行的指针 
int NotDanger(int row,int j,int (*chess)[8])//比较不同行同列上是否有其他皇后 
{
    int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;
    //判断列方向 
    for(i=0;i<8;i++)
    {
      if(*(*(chess+i)+j)!=0)  //在这之前列上有其他皇后 
        {
            flag1=1;
            break;
        }
        
    }
    for(i=row,k=j;i>=0&&k>=0;i--,k--)
    {
    if(*(*(chess+i)+k)!=0) //左上方 
        {
            flag2=1;
            break;
        }
    }
         for(i=row,k=j;i<8&&k<8;i++,k++)
    {
    if(*(*(chess+i)+k)!=0) //右下方 
        { 
            flag3=1;
            break;
        }
    }
              for(i=row,k=j;i>=0&&k<8;i--,k++)
    {
    if(*(*(chess+i)+k)!=0) //右上方 
        {
            flag4=1;
            break;
        }
    }
              for(i=row,k=j;i<8&&k>=0;i++,k--)
    {
    if(*(*(chess+i)+k)!=0) //左下方 
        {
            flag5=1;
            break;
        }
    }

    if(flag1||flag2||flag3||flag4||flag5)
    {
        return 0;//如果有一个位置被占 有危险 
    }
    else return 1; 
     
} /*
int noDanger(int row,int j,int (*chess)[8])  
{  
    int flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;  
    int i,k;  
    //判断列  
    for(i=0;i<8;i++)  
    {  
        if(*(*(chess+i)+j)!=0)  
        {  
            flag1=1;  
            break;  
        }  
    }  
    //判断左上方  
    for(i=row,k=j;i>=0&&k>=0;i--,k--)  
    {  
        if(*(*(chess+i)+k)!=0)  
        {  
            flag2=1;  
            break;  
        }  
    }  
    //判断右下方  
    for(i=row,k=j;i<8&&k<8;i++,k++)  
    {  
        if(*(*(chess+i)+k)!=0)  
        {  
            flag3=1;  
            break;  
        }  
    }  
    //判断左下方  
    for(i=row,k=j;i<8&&k>=0;k--,i++)  
    {  
        if(*(*(chess+i)+k)!=0)  
        {  
            flag4=1;  
            break;  
        }  
    }  
    //判断右上方  
    for(i=row,k=j;i>=0&&k<8;k++,i--)  
    {  
        if(*(*(chess+i)+k)!=0)  
        {  
            flag5=1;  
            break;  
        }  
    }  
    if(flag1||flag2||flag3||flag4||flag5)  
    {  
        return 0;  
    }else  
    {  
        return 1;  
    }  
}  */
EightQueen(int row,int n,int (*chess)[8])
{
    int chess2[8][8];
    int i,j;
    for(i=0;i<8;i++)
    {
        for(j=0;j<8;j++)
        {
            chess2[i][j]=chess[i][j];
            
        }
    }
    if(8==row)
    {
        printf("第%d 种\n",count+1);
        for(i=0;i<8;i++)
        {
            for(j=0;j<8;j++)
            printf("%3d ",*(*(chess2+i)+j));
             printf("\n"); 
        }  
        
        count++;  
    }
    else{
        //判断这个位置是否危险 j<列 
        for(j=0;j<n;j++)
        {
            if(NotDanger(row,j,chess2))//尝试每一列是否危险
            {
                
                for(i=0;i<8;i++)
                {
                    //整行所有列的位置赋值为0 
                    *(*(chess2+row)+i)= 0;
                } 
                *(*(chess2+row)+j)=1;//皇后的位置赋值为1
                EightQueen(row+1,n,chess2);//继续往下一行 递归 
            } 
        } 
    }
}

 int main()
 {
     int chess[8][8],i,j;
     for(i=0;i<8;i++)
     {
         for(j=0;j<8;j++)
         chess[i][j]=0; 
     }
     EightQueen(0,8,chess);
     printf("总共有%d种解决方法",count);
     return 0;
 }

 

以上是关于Python用迭代(yield)和递归解决八皇后问题的主要内容,如果未能解决你的问题,请参考以下文章

Python----递归------Eight Queens 八皇后问题

八皇后 递归or迭代

八皇后--python代码

八皇后问题Python实现

八皇后,回溯与递归(Python实现)

算法入门经典-第七章 例题7-2 八皇后问题