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