<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0

    // N Queens Problem
    // 試探-回溯算法,遞歸實現

    // sum用來記錄皇后放置成功的不同布局數;upperlim用來標記所有列都已經放置好了皇后。
    long sum = 0, upperlim = 1;?????

    // 試探算法從最右邊的列開始。
    void test(long row, long ld, long rd) 。
    {
    ?? if (row != upperlim)
    ?? {
    ? // row,ld,rd進行“或”運算,求得所有可以放置皇后的列,對應位為0,
    ????????? // 然后再取反后“與”上全1的數,來求得當前所有可以放置皇后的位置,對應列改為1。
    ????????? // 也就是求取當前哪些列可以放置皇后。
    ? long pos = upperlim & ~(row | ld | rd);
    ? while (pos) // 0 -- 皇后沒有地方可放,回溯。
    ? {
    ?// 拷貝pos最右邊為1的bit,其余bit置0。
    ?// 也就是取得可以放皇后的最右邊的列。
    ?long p = pos & -pos;??????????????????????????????????????????????

    ?// 將pos最右邊為1的bit清零。
    ???????????????? // 也就是為獲取下一次的最右可用列使用做準備,
    ???????????????? // 程序將來會回溯到這個位置繼續試探。
    ?pos -= p;???????????????????????????

    ?// row + p,將當前列置1,表示記錄這次皇后放置的列。
    ?// (ld + p) << 1,標記當前皇后左邊相鄰的列不允許下一個皇后放置。
    ?// (ld + p) >> 1,標記當前皇后右邊相鄰的列不允許下一個皇后放置。
    ???????????????? // 此處的移位操作實際上是記錄對角線上的限制,只是因為問題都化歸
    ???????????????? // 到一行網格上來解決,所以表示為列的限制就可以了。顯然,隨著移位
    ???????????????? // 在每次選擇列之前進行,原來N×N網格中某個已放置的皇后針對其對角線
    ???????????????? // 上產生的限制都被記錄下來了。
    ?test(row + p, (ld + p) << 1, (rd + p) >> 1);?????????????????????????????
    ? }
    ?? }
    ?? else???
    ?? {
    ?// row的所有位都為1,即找到了一個成功的布局,回溯。
    ? sum++;
    ?? }
    }

    int main(int argc, char *argv[])
    {
    ?? time_t tm;
    ?? int n = 16;

    ?? if (argc != 1)
    ? n = atoi(argv[1]);
    ?? tm = time(0);

    ?? // 因為整型數的限制,最大只能32位,
    ?? // 如果想處理N大于32的皇后問題,需要
    ?? // 用bitset數據結構進行存儲。
    ?? if ((n < 1) || (n > 32))?????????????????
    ?? {
    ? printf(" 只能計算1-32之間\n");
    ? exit(-1);
    ?? }
    ?? printf("%d 皇后\n", n);

    ?? // N個皇后只需N位存儲,N列中某列有皇后則對應bit置1。
    ?? upperlim = (upperlim << n) - 1;?????????

    ?? test(0, 0, 0);
    ?? printf("共有%ld種排列, 計算時間%d秒 \n", sum, (int) (time(0) - tm));
    }

    上述代碼容易看懂,但我覺得核心的是在針對試探-回溯算法所用的數據結構的設計上。
    程序采用了遞歸,也就是借用了編譯系統提供的自動回溯功能。

    算法的核心:使用bit數組來代替以前由int或者bool數組來存儲當前格子被占用或者說可用信息,從這

    可以看出N個皇后對應需要N位表示。
    巧妙之處在于:以前我們需要在一個N*N正方形的網格中挪動皇后來進行試探回溯,每走一步都要觀察

    和記錄一個格子前后左右對角線上格子的信息;采用bit位進行信息存儲的話,就可以只在一行格子也

    就是(1行×N列)個格子中進行試探回溯即可,對角線上的限制被化歸為列上的限制。
    程序中主要需要下面三個bit數組,每位對應網格的一列,在C中就是取一個整形數的某部分連續位即可


    row用來記錄當前哪些列上的位置不可用,也就是哪些列被皇后占用,對應為1。
    ld,rd同樣也是記錄當前哪些列位置不可用,但是不表示被皇后占用,而是表示會被已有皇后在對角線

    上吃掉的位置。這三個位數組進行“或”操作后就是表示當前還有哪些位置可以放置新的皇后,對應0

    的位置可放新的皇后。如下圖所示的8皇后問題求解得第一步:
    row:??????? [ ][ ][ ][ ][ ][ ][ ][*]
    ld:???????? [ ][ ][ ][ ][ ][ ][*][ ]
    rd:???????? [ ][ ][ ][ ][ ][ ][ ][ ]
    ------------------------------------
    row|ld|rd:? [ ][ ][ ][ ][ ][ ][*][*]
    所有下一個位置的試探過程都是通過位操作來實現的,這是借用了C語言的好處,詳見代碼注釋。

    posted on 2006-04-28 16:45 SIMONE 閱讀(441) 評論(1)  編輯  收藏

    FeedBack:
    # 所有下一個位置的試探過程都是通過位操作來實現的,這是借用了C語言的好處,詳見代碼注釋。
    2006-08-07 15:07 | 所有下一個位置的試探過程都是通過位操作來實現的,這是借用了C語言的好處,詳見代碼注釋。
    所有下一個位置的試探過程都是通過位操作來實現的,這是借用了C語言的好處,詳見代碼注釋。  回復  更多評論
      

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 黄色网址大全免费| 欧美色欧美亚洲另类二区| 中文字幕乱理片免费完整的| 国产又黄又爽又猛的免费视频播放| 亚洲精品自偷自拍无码| 无码一区二区三区免费视频| 亚洲精品无码中文久久字幕| 国产一级淫片a免费播放口之 | 亚洲天堂中文字幕在线观看| 三年片在线观看免费大全| 亚洲国产超清无码专区| 两个人的视频高清在线观看免费| 日本亚洲色大成网站www久久| 日本xxwwxxww在线视频免费| 日日狠狠久久偷偷色综合免费| 国产aⅴ无码专区亚洲av麻豆| 日本高清不卡aⅴ免费网站| 日本久久久久亚洲中字幕| 国产精品无码亚洲一区二区三区| 免费一级毛片免费播放| 好猛好深好爽好硬免费视频| 亚洲国产精品国自产拍电影| 国产精品爱啪在线线免费观看| 亚洲人成无码网站在线观看| 一本久到久久亚洲综合| 亚洲一卡2卡3卡4卡5卡6卡| 日本免费一区尤物| 巨胸喷奶水视频www免费视频| 亚洲成人黄色在线| 亚洲第一页综合图片自拍| 国产日韩AV免费无码一区二区| 91亚洲国产成人久久精品| 国产成人综合久久精品免费| 最新久久免费视频| 亚洲中文字幕精品久久| 亚洲综合精品网站在线观看| 最近2019中文字幕免费大全5| 亚洲AV成人精品一区二区三区 | 亚洲AV无码专区国产乱码电影| 99在线精品免费视频九九视| 四虎一区二区成人免费影院网址|