关于回溯和后宫

  这是八皇后问题的升级版,主要是一个荒淫无道的国王娶的一堆皇后瓜分天下的故事。不清楚的同学请转身百度,这里小子就不多说了。

  回溯是我们玩迷宫游戏专用的一种思维模式。主要是先沿着一个方向走,若干步后若无法继续走下一步,则退回一步,朝另一个方向探索,直到终点或返回起点。所以我们可以先从第一行左边开始,一个一个的往下一行放置皇后,每放置一个皇后,判断一次是否与之前所放置的皇后的领域有所冲突。

  判断项有三项,分别是列、主对角线、副对角线。若是领域已被占领,则判伪;若未被占领,则判真。判真的情况下,该点即可作为其中一个可能的答案。让我们来看一下如何去判断领域是否冲突:

    1.列的领域比较好判断,就是一个数组,角标和已放置的皇后的横坐标相同的,即标记为1,表示已有皇后将此列占领,未占领的即标记为0。

    2.主对角线较为复杂,我们先看下边的图:

关于回溯和后宫

       不难得出,同一主对角线的横纵坐标的差是相同的,那么就将差值当做判断数组的角标,用1、0分别标记已占领和未占领,不过有些坐标的差值会是负值,但数组的角标不会是负值,所以为了防止这种情况,要为差值同一加上一个数,以保证结果是正值。

    3.副对角线的判断方法也可从上图推出,这里就交给同学们去思考了。

  以上就是该题的思考过程,代码如下:

 1 #include<stdio.h>

 2 int n;//有n个皇后 

 3 int sum=0;//方法总数 

 4 int flag2[101]={0};//A对角线标

 5 int flag3[101]={0};//B对角线标

 6 int ans[9]={0};//放置坐标,角标为x,数据为y 

 7 int flag1[9]={0};//列标

 8 void out();//该函数主要用于方法数统计与输出结果 

 9 void search(int k);//用于回溯,从第k行开始放置 

10 int main()

11 {

12     scanf("%d",&n);

13     search(1);//从第1行开始 

14     return 0;

15 }

16 void search(int k)

17 {

18     int i;

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

20     {

21         if( (!flag1[i]) && (flag2[i-k+10]==0) && (flag3[i+k]==0) )

22         /*判断语句第一节判断这一列是否在之前皇后的领域中,

23         第二节判断主对角线,第三节判断副对角线*/

24         {

25                 ans[k]=i;

26                 flag1[i]=1;

27                 flag2[i-k+10]=1;

28                 flag3[i+k]=1;

29                 if(k==n)    out();//若到边界即达成一种情况 

30                 else    search(k+1);//未到边界则继续探索 

31                 flag1[i]=0;

32                 flag2[i-k+10]=0;

33                 flag3[i+k]=0;

34         }

35     }

36 }

37 void out()

38 {

39     int i;

40     sum++;

41     printf("%d:\n",sum);

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

43         printf("(%d,%d)\n",i,ans[i]);

44 }

   代码如有错误,欢迎指出,如果这篇博客给了读者帮助,那是小子的荣幸。

你可能感兴趣的:(回溯)