八皇后问题求解

我今天好不容易上了一次课,然后数据结构老师给我们留大作业,丧心病狂,先解决一个叫八皇后的问题。

题目背景:

【问题描述】

在一个8×8的棋盘里放置8个皇后,要求每个皇后两两之间不相"冲"(在每一横列竖列斜列只有一个皇后)。

【问题分析】

数组a、b、c分别用来标记冲突,a数组代表列冲突,从a[0]~a[7]代表第0列到第7列,如果某列上已经有皇后,则为1,否则为0;

数组b代表主对角线冲突,为b[i-j+7],即从b[0]~b[14],如果某条主对角线上已经有皇后,则为1,否则为0;

数组c代表从对角线冲突,为c[i+j],即从c[0]~c[14],如果某条从对角线上已经有皇后,则为1,否则为0;

【基本要求】

[if !supportLists](1) [endif]用递归算法实现

[if !supportLists](2) [endif]输出所有棋盘状态,其中空的地方为“*”,放置皇后的地方为“@”

11.最小生成树求解

【问题描述】

在n个城市之间建设网络,只需保证连通即可,求最经济的架设方法。

【基本要求】

(1)假设已知n个城市之间的网络是一个带权连通无向图。

(2)用邻接矩阵COST表示给定的带权连通无向图。知阵元素定义为

(3)利用普里姆或克鲁斯卡尔算法求图的最小生成树。

然后我们现在工具问题的描述进行分析:

首先,可归纳问题的条件为,8皇后之间需满足:

             1.不在同一行上

             2.不在同一列上

             3.不在同一斜线上

             4.不在同一反斜线上

     这为我们提供一种遍历的思路,我们可以逐行或者逐列来进行可行摆放方案的遍历,每一行(或列)遍历出一个符合条件的位置,接着就到下一行或列遍历下一个棋子的合适位置,这种遍历思路可以保证我们遍历过程中有一个条件是绝对符合的——就是下一个棋子的摆放位置与前面的棋子不在同一行(或列)。接下来,我们只要判断当前位置是否还符合其他条件,如果符合,就遍历下一行(或列)所有位置,看看是否继续有符合条件的位置,以此类推,如果某一个行(或列)的所有位置都不合适,就返回上一行(或列)继续该行(或列)的其他位置遍历,当我们顺利遍历到最后一行(或列),且有符合条件的位置时,就是一个可行的8皇后摆放方案,累加一次八皇后可行方案的个数,然后继续遍历该行其他位置是否有合适的,如果没有,则返回上一行,遍历该行其他位置,依此下去。这样一个过程下来,我们就可以得出所有符合条件的8皇后摆放方案了。这是一个深度优先遍历的过程,同时也是经典的递归思路。

      接下来,我们以逐列遍历,具体到代码,进一步说明。

        首先,从第一列开始找第一颗棋子的合适位置,我们知道,此时第一列的任何一个位置都是合适的,当棋子找到第一个合适的位置后,就开始到下一列考虑下一个合适的位置,此时,第二列的第一行及第二行显然就不能放第二颗棋子了,因为其与第一个棋子一个同在一行,第二列第二行同在一条斜线上。第二列第三行成为第二列第一个合适的位置,以此类推,第三列的第5行又会是一个合适位置,这个过程中,我们注意到,每一列的合适位置都是受到前面几列的位置所影响,归纳如下:

      假设前面1列的棋子放在第3行,那当前列不能放的位置就一定是3行,2行,4行。因为如果放在这三行上就分别跟前一列的棋子同在一行、同在斜线、同在反斜线上,不符合我们的要求。现在我们用cols数组来表示8个列棋子所放的行数,数组下标从0开始,其中数组下标表示列数,数组的元素值表示该列棋子所在行数,当前列为N(N>=0,N<8),即cols[N-1]=3,则有:

                      cols[N] != cols[N-1](=3,表示不在同一行)

                      cols[N] != cols[N-1]-1(=3-1=2,表示不在同一斜线上)

                      cols[N]!=cols[N-1]+1(=3+1,表示不在同一反斜线上)

      这里我们注意到,如果N-2列存在的话,那么我们还要考虑当前列N不与N-2列的棋子同行,同斜线,同反斜线。把当前列N的前面的某一列设为m,则m的所有取值为{m>=0,m

                    cols[N] != cols[m](与第m列的棋子不在同一行)

                    cols[N] != cols­­[m] -(N-m)(>=0 ,与第m列的棋子不在同一斜线上)

                    cols[N] != cols­­[m] + (N-m)  (<=8-1,与第m列的棋子不在同一反斜线上)          

           具体到代码,很显然,取m的所有值只需要一句循环,同时我们为每一列定义一个长度为8的布尔数组row[],下标同样是从0开始,我们规定当row[i]=true时,表示该列第i行不能放棋子。这样我们就能写成下列程序段了:


棋表图


标记

增加一点:你其实也可以这样子想,我某一行和下面一行的横坐标数字相差不能超出集合下标的差。因为你这样子想,我两行最多相差16,因为每次都是先遍历第一行后再遍历第二行,所以不能超出这个范围。

第二点是:不能出现重复元素。重复了还玩个球球。就是集合表示的元素。

public static int num =0; //累计方案总数

public static final int MAXQUEEN =8;//皇后个数,同时也是棋盘行列总数

public static int[]cols =new int[MAXQUEEN]; //定义cols数组,表示8列棋子摆放情况

public Queen8() {//核心函数

    getArrangement(0);

    System.out.print("/n");

    System.out.println(MAXQUEEN+"皇后问题有"+num+"种摆放方法。");

}

public void  getArrangement(int n) {

//遍历该列所有不合法的行,并用rows数组记录,不合法即rows[i]=true

    boolean[] rows =new boolean[MAXQUEEN];

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

rows[cols[i]] =true;

        int d = n - i;

        if (cols[i] - d >=0) rows[cols[i] - d] =true;

        if (cols[i] + d <=MAXQUEEN -1) rows[cols[i] + d] =true;

    }

for (int i =0; i

//判断该行是否合法

        if (rows[i])continue;

        //设置当前列合法棋子所在行数

        cols[n] = i;

        //当前列不为最后一列时

        if (n

getArrangement(n +1);

        }else {//累计方案个数

            num++;

            //打印棋盘信息

            printChessBoard();

        }

}

}

public void printChessBoard(){

System.out.print("\n"+"第"+num+"种走法 "+"\n");

    for(int i=0;i

for(int j=0;j

if(i==cols[j]){

System.out.print("0 ");

            }else

                System.out.print("+ ");

        }

System.out.print("\n");

    }

}

public static void main(String args[]){

Queen8 queen =new Queen8();

    queen.printChessBoard();

}

        思路嘛其实很简单,就是为了避免两个棋子有相互接触的空间,然后先遍历第一行,然后得到位置以后放到数组里面,然后遍历第二行,获取位置放到数组,然后进行比对,看是否合适,合适继续遍历,不合适就重新返回第一行重新规划位置,继续遍历。

        这种题目属于深度优先遍历的算法,当然也很无聊。就是平常下棋的时候的用的招数,只是平常没有想到还可以做算法,不过作为锻炼思维,倒是一种很好的玩具。这个算法可以运用到递归,不断判断然后return,继续遍历。

OK,介绍完毕。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 前言 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8...
    jacky123阅读 1,510评论 0 3
  • 望江南 花满楼,满心头,香浮袭人柔。道是也还羞。 人如旧,如心休,情动惹人愁。恰似...
    一席之宾阅读 232评论 0 1
  • 第四节 下 总是想将与你的距离拉近一点再拉近一点,可又是那样容易自我否定自我逃离。在迷离的距离里,又出现了更多的...
    叶子程阅读 159评论 1 1
  • 吴军老师的文章中写道 职业选手和业余选手的区别并不在于后者发挥不好,而只是他们不稳定,情绪波动较大...
    山涧百合Y阅读 577评论 1 1