回溯算法

来源:互联网 发布:粉红色的火烈鸟知乎 编辑:程序博客网 时间:2024/06/05 23:48

使用回溯算法解决N皇后问题.

1.        问题描述:

棋盘为N*N的,在该棋盘上放置N个皇后,使得任意两个皇后不在同一行或者同一列或者同一对角线(主对角线和副对角线)。

2.        解题思路:

分析得:必定使得棋盘的每一行每一列均存在且只存在一个皇后,所以遍历所有的行,对每一行,遍历所有的列,使用判断条件排除。

3.        原始程序:

#include<iostream>

using namespace std;

 

int n,ans;// n是棋盘边的格子数;ans是解决方案的个数

int c[100];//存取每一行的列数

 

void recall(int cur);//回溯函数

 

int main()

{

   while(cin>>n)

    {

       ans=0;//每一组必须清空

       recall(0);/下标从0开始

       cout<<ans<<endl;

    }

   return 0;

}

 

void recall(int cur)

{

   if(cur==n)//递归边界:只要走到这里,所有皇后必定不冲突,即得解决方案

    {

       ans++;

    }

   else

    {

       for(int i=0;i<n;i++)

       {

           int ok=1;

           c[cur]=i;//尝试将第cur行的皇后放在第I列

           for(int j=0;j<cur;j++)//检查该皇后是否与以前放的皇后冲突

           {

               if(c[cur]==c[j]||cur+c[cur]==j+c[j]||cur-c[cur]==j-c[j])

/*

因为逐行放置,所以所在的行必定不会冲突;c[cur]==c[j]是列冲突;cur+c[cur]==j+c[j]是副对角线冲突;cur-c[cur]==j-c[j]是主对角线冲突

*/

                {

                    ok=0;

                    break;

                }

           }

           if(ok)

           {

                recall(cur+1);

           }

       }

    }

}

运行结果:

1

1

2

0

3

0

4

2

5

10

6

4

7

40

8

92

9

352

10

724

4.        优化程序(速度更快)

思路:直接用vis[][]这个二维数组来判断当前尝试放的位置所在的列(vis[0][i])、主对角线(vis[1][cur+i])、副对角线(vis[2][cur-i+n])是否已经放了皇后(放了为1,没放为0)。如果没放,那么放上(c[100]用来存储路径,如果不需要打印路径,则不需要该数组);如果放了尝试下一个位置。注意:recall(cur+1)语句执行完以后,表明对于当前的位置已经是求得了结果,所以向上一层程序返回的时候,一定将状态改回:“没被访问”。一般的:如果在回溯法中修改了辅助的全局变量,则一定要及时将他们恢复原状。若函数有多个出口,则需要在每个出口的地方恢复被修改的值。

#include<iostream>

#include<cstring>

using namespace std;

 

int vis[100][100];

int n,ans;

int c[100];

 

void recall(int cur);

 

int main()

{

   while(cin>>n)

    {

       memset(vis,0,sizeof(vis));

       ans=0;

       recall(0);

       cout<<ans<<endl;

    }

   return 0;

}

 

void recall(int cur)

{

   if(cur==n)

    {

       ans++;

    }

   else

    {

       for(int i=0; i<n; i++)

       {

           if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n])

           {

                c[cur]=i;

               vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;

                recall(cur+1);

               vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;

           }

       }

    }

}

运行结果:

1

1

2

0

3

0

4

2

5

10

6

4

7

40

8

92

9

352

10

724

0 0
原创粉丝点击