• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            雁過無痕

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::

            N個數計算24

            問題:

                N113之間的自然數,找出所有能通過加減乘除計算(每個數有且只能用一次)得到24的組合

             

            計算24點常用的算法有:① 任取兩個數,計算后,將結果放回去,再從剩下的數中任取兩個,如此反復直到只剩下一個數;② 先構建前綴/后綴表達式,再計算該表達式;③ 用集合保存中間結果,集合間兩兩進行合并計算得到新集合(或者對給定的一個集合,對其所有的子集合進行合并計算)。

            本文采用第一種方法。定義六種操作符:ADDSUBMULDIVRSUBRDIV,分別對應加、減、乘、除、反減和反除(反減/除:先交換兩個數,再減/除)。

            顯然,取兩個數計算時,六種計算結果可能有重復,可以對這6個結果進行去重(實際上,只要分別對加減(ADDSUBRSUB)和乘除(MULDIVRDIV)的3個計算結果進行去重判斷就可以了,效率和對6個結果去重相差不大)。

            另外一種剪枝方法:保存每個數上次計算時所用的操作符(初始值為空)。所取的兩個數:

            若某個數的上次操作符為減(SUBRSUB),那么不進行加減(ADDSUBRSUB)計算。

            若某個數的上次操作符為除(DIVRDIV),那么不進行乘除(MULDIVRDIV)計算。

            比如:取的兩個數為 a-b c(c的上次操作符任意),如果進行加減計算的話,

            a-b+c  c+a-b重復,

            c-(a-b)c+b-a重復

            a-b-c  c+b RSUB a重復

            也就是說,上次操作符為減的,進行加減計算時,總可以轉為某個上次操作符為加的表達式,因而可以不計算。同樣,上次操作符為除的,不進行乘除計算。

            當然,還可以考慮記錄位置進行剪枝,這樣避免a+b+ca+c+b都進行計算。但要注意的是:在給定的組合無解時,越多的剪枝方法,極有可能提高搜索效率,但在給定的組合有解時,很可能反而降低搜索效率

            另外,對有解時輸出的表達式的處理對程序的性能影響很大。如果每次計算都保存對應的表達式,會進行大量的字符串操作,嚴重影響性能。實際上,每次計算只要保存取出的兩個數的位置和所進行計算的操作符就夠了,最終需要輸出表達式時,只要模擬一下遞歸函數調用過程,進行相應的字符串操作。

            下面是程序(gcc 4.5,優化參數-O2)在T4200/2G單核下運行的結果,計算10個數,646646個組合只用了不到13分鐘。


             
            N113之間的數的所有組合,計算24

            N

            4

            5

            6

            7

            8

            9

            10

            時間(ms)

            78

            610

            4157

            19593

            160922

            173766

            764328

            有解組合數

            1362

            6104

            18554

            50386

            125969

            293930

            646646

            總組合

            1820

            6188

            18564

            50388

            125970

            293930

            646646

            總表達式

            1124776

            15656645

            105278906

            492587616

            3760744504

            4535030813

            19912345238

            表達式A

            457549

            11864184

            88679768

            409129896

            1173803224

            4535030813

            19912345238

            表達式B

            667227

            3792461

            16599138

            83457720

            2586941280

            0

            0

            總函數調用

            1482939

            20950792

            141892513

            669790534

            5258218577

            6112529945

            26948662625

            函數調用A

            603206

            15849306

            119160441

            551913059

            1576965280

            6112529945

            26948662625

            函數調用B

            879733

            5101486

            22732072

            117877475

            3681253297

            0

            0

            其中:表達式A/B、函數調用A/B為:給定的n個數有/無解時,所處理的表達式總數和函數調用總次數。

             

                N=8N=9,兩個所用時間只相差13秒,這是由于N8時,有一個組合(81)無解,判斷這個組合無解需110多秒,而計算剩下的125969個組合還不要50秒。


            程序代碼:

            24.cpp
            posted on 2010-08-15 23:20 flyinghearts 閱讀(2356) 評論(0)  編輯 收藏 引用 所屬分類: 算法編程之美C++
            精品久久久久久无码专区不卡| 久久精品日日躁夜夜躁欧美| 国产精品无码久久综合| 久久精品成人免费网站| 日本久久中文字幕| 久久人人爽人人爽人人AV| 亚洲成色999久久网站| 亚洲国产日韩综合久久精品| 99久久精品国产麻豆| 四虎国产精品免费久久| 久久久久人妻精品一区二区三区 | 久久狠狠高潮亚洲精品| 久久国产免费直播| 久久国产欧美日韩精品| 欧美国产精品久久高清| 国产69精品久久久久777| 亚洲精品国精品久久99热| 久久不射电影网| 色综合久久夜色精品国产| 久久久精品免费国产四虎| 中文精品久久久久人妻不卡| 久久精品免费大片国产大片| 久久精品一区二区三区不卡| 久久久久亚洲AV无码观看 | 久久久久综合国产欧美一区二区| 日韩精品久久久久久久电影蜜臀 | 亚洲国产精品久久久久网站| 无码日韩人妻精品久久蜜桃| 人妻丰满?V无码久久不卡| 色综合色天天久久婷婷基地| 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 麻豆av久久av盛宴av| 久久久不卡国产精品一区二区| 久久99国产精品久久99| 久久精品人人做人人妻人人玩| 国内精品伊人久久久影院| 无码乱码观看精品久久| 久久国产福利免费| 久久婷婷五月综合色99啪ak| 日韩欧美亚洲国产精品字幕久久久| 国内精品久久久久久久亚洲|