經過搜索獲得一棵樹形圖函數
策略:只要能發現沒走過的點,就走到它。有多個點可走就隨便挑一個,若是無路可走就回退,再看有沒有沒走過的點可走。spa
在圖上尋找路徑【少數可用最短路解決】:最短路不能解決路徑有順序的,也就是若是路徑的邊權與以前通過的點火這路有關,那就只能深搜code
解決遞歸形式的問題blog
有後效性的選擇問題遞歸
組合問題隊列
狀態可能不少,所以數據範圍通常較小源碼
一、狀態表示 class
二、剪枝 效率
剪枝的方法: 擴展
最優答案剪枝
記憶化剪枝
可行性剪枝
……
數據範圍小,搜索
建反圖找團(簡單地說,團是G的一個徹底子圖)
原來輸入建圖是標記的兩點之間不能有連邊,建反圖以後,連邊的就是能夠連通的
剪枝:
1.若是一個點與點i當前沒有連邊,那麼以後永遠都不會連邊,那麼就能夠把點i從最大團候選中刪掉
2.利用可行點剪枝 sum+tot<=ans ,捨棄
3.利用當前答案剪枝ans(2)+tot<=ans
(tot 是團不斷累加的權值,sum是序列裏面剩下的全部東西的權值和
若sum+tot<=ans ,捨棄)
可能組成最大團的點一開始在一個序列裏
取出一個點,不斷擴展,當序列爲空,擴展完了
首先拿出1 ,那麼序列被更新爲與1相連的點
不斷擴展,直到隊列爲空,找完團了
--->sum+tot<=ans
最大團主函數:
爲何找最大團而不是最大獨立集呢??
queue<pair<int,int> > Q; int FindPath(pair<int,int> b,pair<int,int> e) { for (int i=0;i<n;++i) for (int j=0;j<m;++j) dis[i][j]=1e9+10; Q.push(b); dis[b.first][b.second]=0; while (!Q.empty()) { pair<int,int> u=Q.front(); Q.pop(); int x=u.first,y=u.second; for (int i=0;i<4;++i) { int tx=x+dx[i],ty=y+dy[i]; if (CoordValid(tx,ty) && mp[tx][ty]!=0 && dis[tx][ty]>dis[x][y]+1) { dis[tx][ty]=dis[x][y]+1; Q.push(make_pair(tx,ty)); } } } return dis[e.first][e.second]; }
記錄當前素數的值
每次選擇一個位置,將其該改成另外一個數
檢查新的數是不是素數
(Python源碼)
BFS部分
BFS
廣搜通常用於狀態表示比較簡單求最優策略的問題l
優勢:是一種完備策略,即只要問題有解,它就必定能夠找到解。而且,廣度優先搜索找到的解,還 必定是路徑最短的解。
缺點:盲目性較大,尤爲是當目標節點距初始節點較遠時,將產生許多無用的節點,所以其搜索效率較低。須要保存全部擴展出的狀態,佔用的空間大
深搜幾乎能夠用於任何問題
只須要保存 從起始狀態到當前狀態路徑上的節點
根據題目要求憑藉本身的經驗和對兩個搜索的熟練程度作出選擇
選擇連續的香蕉時最優
枚舉選擇的香蕉起始位置,計算答案
Check函數:
一、 已知,在首位狀態固定後,後續的操做是肯定的。
二、 只須要枚舉首位是否按便可。
①不是一條行走路徑:只有兩棵被踩踏的水稻;
②是一條行走路徑,但不包括(2,6)上的水道;
③不是一條行走路徑:雖然有3棵被踩踏的水稻,
但這三棵水稻之間的距離間隔不相等。
例如,圖4的答案是7,
由於第6行上所有水稻剛好構成一條青蛙行走路徑。
枚舉主函數
枚舉獲得最大步數
枚舉:基於已知信息的猜想,從可能的答案集合中枚舉並驗證
驗證複雜度儘量小
枚舉範圍儘量小(利用條件縮小枚舉空間)
選擇合理的枚舉順序(正序,倒序)
枚舉什麼?
怎麼枚舉?
怎麼減小枚舉?
二進制枚舉
推導最後一行
二進制的枚舉通常用以枚舉集合
對集合的枚舉涉及到不一樣的集合內部元素的選擇
枚舉子集
for(int S1=S;S1!=0;S1=(S1-1)&S){
S2=S^S1;
}