第五章報告+學期末總結
1. 對回溯演算法的理解
回溯法也是一個尋求問題最優解的演算法,本質是一種深度優先搜尋演算法的改進。
回溯法的基本思路是對於問題的可行解建立成樹,搜尋遍歷每個節點並對其節點狀態進行比較,在全部搜尋完成後,自然的得到的是問題的最優解
關鍵:
1.回溯:回溯函式的設計有基本格式
void Backtrack(int t)//以深度優先的方式遍歷第t層中的某棵子樹 { if(t>n) { Output(x); return; } //遍歷到葉子結點,返回 if (……) { x[t]=1; Backtrack(t+1); } //滿足條件進入左子樹 if (……) { x[t]=0; Backtrack(t+1); } //滿足條件進入右子樹 }//注意Backtrack(t+1)後要將Backtrack(t+1)前進入子樹改變的條件還原
2.剪枝函式的設計:對於一些可以提前確定不可能是最優解的節點,設計這樣的剪枝函式避免對他的搜尋,以提高演算法效率
分為約束函式(不滿足約束條件)和界限函式(得不到最優解)
3.經典0-1揹包問題程式碼:
#include<bits/stdc++.h> using namespace std; int n; double cmax,bestv=0,nowv=0,noww=0; struct P{ doublew,v; }p[1000]; bool cmp(P p1,P p2){ return p1.v/p1.w > p2.v/p2.w ; } double bound(int t){ double cleft=cmax-noww,sum=nowv; while(t<=n && p[t].w<=cleft){ cleft-=p[t].w; sum+=p[t].v; t++; } if(t<=n) sum+=p[t].v/p[t].w*cleft; returnsum ; } void bt(int t){ if(t>n){ if(bestv<nowv) bestv=nowv; } else{ if(noww+p[t].w<=cmax){ noww+=p[t].w; nowv+=p[t].v; bt(t+1); noww-=p[t].w; nowv-=p[t].v; } if(bound(t+1)>bestv){ bt(t+1); } } } int main(){ cin>>n>>cmax; for(int i=1;i<=n;i++) cin>>p[i].w>>p[i].v; sort(p,p+n,cmp); bt(1); cout<<bestv<<endl; return 0; }
2. 學習《演算法分析與設計》課程的收穫
本學期重點學習了分治法,二分搜尋,動態規劃演算法,貪心演算法和回溯法,經過本學期的學習,我對程式設計的演算法設計有了初步的概念,瞭解了處理一些常規問題時可以使用的演算法,策略和技巧;
通過對演算法設計和分析的學習,我認識到,對於一些經典的問題,有許多經典的演算法,這些是我們應該深入學習和掌握瞭解的,
在此基礎上,去解決現實存在的更復雜的問題,往往需要對經典演算法舉一反三,並且不斷地根據實際情況優化演算法,
才能獲得更低的時間複雜度和空間複雜的,而一個小於n^2的時間複雜度,是大部分問題所追求的。
學習分治,二分搜尋演算法:我明白了最基礎的搜尋查詢演算法,並且瞭解了遞迴呼叫的時間複雜度分析
學習動態規劃演算法:我瞭解了對於很多邊計算邊比較的問題,有這樣一種演算法可能使時間複雜度從n^3降低為n^2
學習貪心演算法:我瞭解了對於大規模問題只要滿足最優子結構性質和區域性最優性質就可以從子問題開始設計一個最直接的演算法直接求解
學習回溯法:我瞭解了對於“分層”的問題,可以做樹的深度優先遍歷,遞迴呼叫函式,搜尋每個節點,比較得出最優解
3. 你在學習過程中曾遇到了哪些困難,希望老師或助教及時給予幫助。
對於動態規劃演算法,我時常不知道如何構建表格,不知道是一維表格合適還是二維表格合適,如果題目比較複雜,我很難決定用那些資料作為表的元素
比如0-1揹包問題,如果不看書,我幾乎不可能想出來m[i][j]中i代表揹包剩餘容量,j代表第j個裝入的物品。
4. 你對本門課程的教學有哪些建議
暫無