经过搜索获得一棵树形图函数
策略:只要能发现没走过的点,就走到它。有多个点可走就随便挑一个,若是无路可走就回退,再看有没有没走过的点可走。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;
}