1. 程式人生 > >poj1011(dfs+目前做的最好的剪枝)

poj1011(dfs+目前做的最好的剪枝)

題意:n根不同長度的小棍,拼成若干長棍,要這些長棍的長度相等,並且小棍剛好用完,問拼成長棍的最短長度是?
前話:這題是在暑假第一天搜尋專題下,作為自己複習的練手題目,其實是又一次加深學習搜尋的思想(弱已跪)和回溯的一些理解。
思路:表明上初看此題就像是搜尋,(我開始也想過二分,這並不是只有一種可行,而是找到最短),首先考慮搜尋的方向,最短,那肯定是從最短的情況開始遞增,最短的可能情況那肯定就是最長的的單個棍子,所以首先把這些小棍排序,從大到小,並計算這些棍子總和,拼成的長棍的長度從最長的小棍開始搜尋,搜尋的過程也是判斷,用總和除以這個長度得到應該拼成的長棍個數,遞迴搜尋判斷小棍之間能否相組合成滿足這麼多個長度相等的長棍。
在搜尋過程中 注意四個地方可以剪枝(效果還是很驚人的)
1.搜尋的起點是最長的小棍長度,而不用從1開始(最明顯,容易可以想到)。
2.用一個used陣列標記,哪個小棍用過了。(前兩個都是最基礎,當我沒說)。
3.(威力巨大)當一個棍子發現沒有棍子可以與他配對,直接跳過,後面的棍子嘗試,這次棍子長度絕對不滿足,直接嘗試下一個長度。
4.當一個棍子的長度已經被否定不能與這個棍子配對,避免出現下個與上個相同的情況,搜尋重複,由於排好序的,如果這個和下個相等,就移到不相等的數字再嘗試。
以已下這組測試資料為例:
45
15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8
不剪枝 用c變數記載遞迴次數900多萬次
剪枝完成後 僅僅4萬多次 遞迴。
由於開始看到書上標答是回溯的寫法,深搜帶一個返回值,對於一直習慣搜尋返回void 的我開始覺得不好理解…後來測試各種資料後,我自己寫出我習慣寫的普通深搜,感覺兩者從時間複雜度上沒神馬區別。回溯也是第一次用,不好評價,以後慢慢理解。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[80],sum,num,n,c;
bool used[80];
bool cmp(int a,int b)
{
    return  a>b;
}

bool dfs(int stick,int len,int pos)
{
    //c++;
    if(stick==num)
     return true;
    for(int
i=pos;i<n;i++) { if(used[i]) continue; if(a[i]+len==sum/num) { used[i]=true; if(dfs(stick+1,0,0)) return true; used[i]=false; return false; } else if(a[i]+len<sum/num) { used[i]=true; if
(dfs(stick,len+a[i],i)) return true; used[i]=false; if(len==0) return false; while(a[i]==a[i+1]) i++; } } return false; } int main() { //c=0; while(scanf("%d",&n)&&n) { sum=0; for(int i=0;i<n;i++){ scanf("%d",&a[i]); sum+=a[i]; } sort(a,a+n,cmp); for(int aim=a[0];aim<=sum;aim++) { if(sum%aim) continue; num=sum/aim; memset(used,false,sizeof(used)); if(dfs(0,0,0)) { printf("%d\n",aim); //cout<<c<<endl; break; } } } return 0; }

我寫的普通深搜

#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int a[65],used[65],n,sum,num,flag,c;
bool cmp(int a,int b)
{
    return a>b;
}

void dfs(int stick,int len,int pos)
{
   // c++;
    if(flag)
        return;
    if(stick==num){
        flag=1;
        return;
    }
    for(int i=pos;i<n;i++)
    {
        if(used[i]) continue;
        if(a[i]+len==sum/num)
        {
            used[i]=1;
            dfs(stick+1,0,0);
            //if(flag) return;//想起到剪枝作用,收到後,回到上個 搜尋就直接結束,而然並沒神馬作用。
            used[i]=0;
            return;
        }
        else if(a[i]+len<sum/num)
        {
            used[i]=1;
            dfs(stick,len+a[i],i+1);
            //if(flag) return;
            used[i]=0;
            if(len==0) return;

            while(a[i]==a[i+1])i++;
        }
    }
}

int main()
{
    //c=0;
    while(scanf("%d",&n)&&n)
    {
        flag=sum=0;
        memset(used,0,sizeof(used));
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        sort(a,a+n,cmp);
        for(int i=a[0];i<=sum;i++)
        {
            if(sum%i) continue;
            num=sum/i;
            dfs(0,0,0);
            if(flag){
            printf("%d\n",i);
            break;
            }
        }
        //cout<<c<<endl;

    }
    return 0;
}

相關推薦

poj1011(dfs+目前最好剪枝)

題意:n根不同長度的小棍,拼成若干長棍,要這些長棍的長度相等,並且小棍剛好用完,問拼成長棍的最短長度是? 前話:這題是在暑假第一天搜尋專題下,作為自己複習的練手題目,其實是又一次加深學習搜尋的思想(弱

POJ1011 dfs剪枝

  B站上老師已經講的很清楚了,我掛個程式碼; B站:https://www.bilibili.com/video/av10046345/?p=18 #include<cstdio> #include<iostream> #include<algo

不忘初心,努力最好的自己

四周年征文 學習 又是一個平靜的夏日夜晚,收拾好家務,貼上一貼面膜,準時的坐在電腦前,來到51CTO,其實這樣的生活,已經成為了每天的必然,為了曾經的夢想,為了成為更好的自己,不負時光。 十年前的那個夏天,我畢業於一座三線城市的普通二本院校,畢業後考入一個縣城的政府機關信息中心的網

#51CTO學院四周年#不忘初心,努力最好的自己 ——zhaiken

軟考 cissp 我是2014年報名軟考,軟考分為基礎知識、案例、論文三個部分,其中案例和論文是比較難,對考生的項目知識和實際項目管理能力要求比較高,為了幫忙通過考試,盡快掌握案例考點和論文技巧,我學習了趙勝老師的”信息系統項目管理師-經驗分享與論文深度解析視頻寶典”和”備戰2015信息系統項目管理師

人皆為才的天搜股份,如何讓員工最好的自己?

計劃 最好的 src 最大 fad 不同 自我驅動 團隊 blog 在今年雅加達亞運會電子競技表演賽上,中國代表隊勇奪桂冠,輝煌戰績背後是電競選手每日不低於10小時的高強度訓練。這種系統化的訓練培養,才最大程度激發了中國電競代表隊成員的潛能。人與人的差距,智商從來只是很小一

hdu1010Tempter of the Bone(dfs加奇偶剪枝

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 151

hdu 1010 Tempter of the Bone dfs+奇偶性剪枝

#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int n,m,t; char map[8]

用心行走——《最好的新教師》讀後感3200字

用心行走——《做最好的新教師》讀後感3200字: 作者:何英。我是一名新教師,踏上工作崗位之初,我感覺自己像一個大陀螺,不停的在原地旋轉旋轉,卻找不到方向。這種感覺讓我一度懷疑,這還是我踏上教師崗位的初衷嗎?正因為這份迷茫,讓我一拿到劉勝峰老師的《做最好的新教師》便愛不釋手。 書分五章,直面24個教師專業成長

jieba--最好用的中文分片語件詳解【1】

寫在最前面: 今天只做基礎使用介紹,關於分詞使用的演算法、模型會在下面的部落格詳細介紹。 特點: jieba是一款中文分片語件,支援python2,3 支援三種分詞模式: 精確模式,試

jieba--最好用的中文分片語件詳解【2】

寫在最前面: 今天有時間,再講一講jieba分詞的詞典。 載入詞典: 首先,這是原來的分詞方式及其結果: 開發者可以指定自己自定義的詞典,以便包含 jieba 詞庫裡沒有的詞。雖然 jieba 有新詞識別能力,但是自行新增新詞可以保證更高的正確率 import

jieba--最好用的中文分片語件詳解【3】

寫在最前面: null 基於TF-IDF演算法的關鍵詞抽取 import jieba.analyse jieba.analyse.extract_tags(句子,topK = 20,

最好的自己,最好的設計。

1、static變數與實體變數的區別? static是靜態變數,static可以通過類名直接訪問 記憶體方面的不同:static在定義的時候jvm就會分配空間, 而實體變數只有在建立物件的時候才會去分配空間 2、int Integ

Rainbond 5.0.4版本釋出-最好用的雲應用作業系統

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

POJ1011 經典DFS+剪枝

題意: 給你n個小棒碎片,要求還原原棒長,求最短原棒長 要點: 經典搜尋題,有很多剪枝,很早之前就想做一下,現在終於有水平可以做了,感覺水平還是有進步的,原來根本看不懂,現在好歹看的懂了,主要是各種剪枝實在是比較難想到。 從最大的一個碎片開始到碎片總和,一個個DFS是否為原

hdoj1455 poj1011 nyoj293 Sticks【DFS+剪枝

Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 128649 Accepted: 30149 Descrip

poj1011 木棒 dfs+剪枝

目描述 喬治拿來一組等長的木棒,將它們隨機地砍斷,使得每一節木棍的長度都不超過50個長度單位。然後他又想把這些木棍恢復到為裁截前的狀態,但忘記了初始時有多少木棒以及木棒的初始長度。請你設計一個程式,幫助喬治計算木棒的可能最小長度。每一節木棍的長度都用大於零的整數表示。 In

poj1011——Sticks(dfs+剪枝

Description George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants

poj1011——剪枝dfs搜尋題

題意:有好多根短棍他們可以組合成n個長度相同的長棍求長棍的最短值粗略參考了網上的1個剪枝技巧:排序,捨棄 之前相同長卻搜失敗的棍子然後開始自己編寫發現速度超時, 對著數字推演半天,最終發現len=0,也

目前最好用的芯片低功耗方法-Multi-bits register

低功耗 寄存器 soc ic設計 目前芯片功耗的問題越來越突出,我們到底需要采用什麽樣的方法才能降低功耗,並且對我們的DUT改動最小呢?(人心貪婪啊,吃在碗裏,看著鍋裏)。 不過真的有這麽一種方法,不僅可以使的芯片功耗降低,而且對設計的改動幾乎為0。你一定問是什麽大招。不過了解之前稍微有點耐心

NYOJ 927 The partial sum problem 【DFS】+【剪枝

har int 輸出 amp lines cmp dsm sim pri The partial sum problem 時間限制:1000 ms | 內存限制:65535 KB 難度:2 描寫敘述One day,Tom’s