My Carelessness

Back to your page!


Or leave your comments here.

RegendLa

导航

关于回溯和后宫

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

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

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

    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 }

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

posted on 2015-05-20 10:21  最爱七  阅读(193)  评论(1)    收藏  举报




Thanks for your coming!
If what you read helps,I would appreciate!