C语言技巧之搜索剪枝
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
} return 0;
} if(find) { for (i=0;i<9;i++) { for (j=0;j<ways[i];j++) { cout<<i+1<<" "; } } cout<<endl; return 0; }
temp[i]=clock[i]; for (j=0;j<9;j++) { temp[i]+=ways[j]*move[j][i]; } temp[i]%=4; if(temp[i]!=0) { find=false; break; }
} }
(1) 循环解决的深搜(此题又像枚举) 1166 The Clocks
Description
There are nine clocks in a 3*3 array (figure 1). The goal is to return all the dials to 12 o'clock with as few moves as possible. There are nine different allowed ways to turn the dials on the clocks. Each such way is called a move. Select for each move a number 1 to 9. That number will turn the dials 90' (degrees) clockwise on those clocks which are affected according to figure 2 below.
参考代码:
#include <iostream> using namespace std; int temp[9];//存储每一列时钟的状态 int main() {
int move[9][9]={
{1,1,0,1,1,0,0,0,0}, {1,1,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0}, {1,0,0,1,0,0,1,0,0}, {0,1,0,1,1,1,0,1,0}, {0,0,1,0,0,1,0,0,1}, {0,0,0,1,1,0,1,1,0}, {0,0,0,0,0,0,1,1,1}, {0,0,0,0,1,1,0,1,1} }; int ways[9]; bool find; int clock[9];
Sample Input
3 3 0 2 2 2 2 1 2
Sample Output
4 5 8 9 大概题意:
有九个时钟,每个时钟只有 4 种状态:12:00,3:00,6:00,9:00。分别用 0, 1,2,3 代替。现在有 9 种操作,如表 2 所示,每种操作能使对应的钟顺时针旋转 90 度。 现在给出 9 个时钟的初始状态,问怎么用最少的操作使得这 9 个时钟都指向 12:00。 输入给出 9 个数字,用 1,2,3,4 代表每个时钟的初始状态。输出要求给出操作代号, 此操作代号按升序排列。
(2) 递归解决的简单搜索 1562 Oil Deposits
Description
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.
4 种状态 9 种操作
解题思想:
可以观察到这九个时钟都是按顺时针旋转,由于求最少的操作数,我们知道一个时钟如果 旋转 4 次,那么它就回到了初始位置,相当于没有操作,那么上面的 4 次操作是多余的, 不可能成为解,因此可以得出结论,每个操作,如操作 1 ABDE 最多只需要操作 3 次,最 少是不操作。 那么 9 个时钟的有 4^9 种方法, 此数字并不是很大, 完全可以在有限的 1000ms 运行出结果。因此可以用最笨的方法解决。本题如果先不对程序加以分析和解剖,洞察问 题的本质和寻找规律,那么将是非常严重的问题,不但效率低,甚至严重超时。
Input
Your program is to read from standard input. Nine numbers give the start positions of the dials. 0=12 o'clock, 1=3 o'clock, 2=6 o'clock, 3=9 o'clock.
深度优先搜索 DFS(有时称为 回溯法) 遵循的搜索策略是尽可能深地搜索图,在深度优先 搜索中,对于最新发现的顶点,如果它还有以此为起点而未探索到的边,就沿此边继续搜 索下去。当结点 V 的所有边都已被探寻过时,搜索将回溯到发现结点 V 有那条边的始结点。 这一过程一直进行到已发现从源结点可达的所有结点为止。如果还存在未被发现的结点, 则选择另一个未发现的结点作为新的源结点重新上面的过程,直至所有的结点都搜索到。
Input
The input contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket.
一 概念介绍
状态(state) 问题在某一时刻的进展情况的数学描述。 算符(operator)/ 状态转移 问题从一种状态变换成另一种(或几种)状态的操作。 解答树 搜索的过程实际是在遍历一个图,它的结点就是所有的状态,有向边对应于算符, 而一个可行解就是一条从起始节点出发到目标状态集中任意一个结点的路径。特个图称为 状态空间(state space) ,这样的搜索称为 状态空间搜索(Single-Agent Search) ,得 到的遍历树称为解答数。 基本搜索法: 枚举 枚举法的基本思想是根据提出的问题枚举所有可能状态,并用问题给定的条件检验哪 些是需要的,哪些是不需要的。能使命题成立,即为其解。枚举算法的特点比较单纯,往 往容易写出程序,也容易证明算法的正确性和分析算法的时间复杂度,可以解决一些很小 的问题。它的缺点是效率特别低,往往很多题目不能用枚举方法,用了只会超时。所以它 适应于容易找到状态并且状态较少的题目。没有信心确定其状态较少,请勿立即动手写程 序!
Output
Your program is to write to standard output. Output a shortest sorted sequence of moves (numbers), which returns all the dials to 12 o'clock. You are convinced that the answer is unique.
//操作表,对对应有操作为 1
//各操作的遍数 //时wk.baidu.com的初始状态
int i,j; for (i=0;i<9;i++) { cin>>clock[i];
} //下面 9 层循环遍历了所有可能的出现的情况 for for for for for for for for for { (ways[0]=0;ways[0]<4;ways[0]++) (ways[1]=0;ways[1]<4;ways[1]++) (ways[2]=0;ways[2]<4;ways[2]++) (ways[3]=0;ways[3]<4;ways[3]++) (ways[4]=0;ways[4]<4;ways[4]++) (ways[5]=0;ways[5]<4;ways[5]++) (ways[6]=0;ways[6]<4;ways[6]++) (ways[7]=0;ways[7]<4;ways[7]++) (ways[8]=0;ways[8]<4;ways[8]++) find=true; for (i=0;i<9;i++) { //对每个时钟旋转
搜索问题
计算机学院 2006 级师范班 程文华 搜索被称为“通用的解题法” ,在算法和人工智能方面占有非常重要的低位,特别是在 各类 ACM 程序设计比赛中非常常见,在题目中一般位于中间位置,作为中等难度的题目出 现。因此我们需要着重掌握各类的搜索算法,才能面对各类即将到来的 ACM 大赛。 “只要功 夫深,铁棒磨成针” , “冰冻三尺,非一日之寒” ,要能熟练的掌握和 AC 比赛中的题目,必 须在熟练掌握各类搜索算法的基础上勤加练题,也是唯一的好方法。 本次讲解中,首先给出有关搜索的基本概念,然后针对各类专题,讲解具体的几个例 题并加于分析(注:题目全部选自 poj 中的题目) 。
专题 1:深度优先搜索 DFS
深度优先搜索有很多呈现形式,一般用递归解决,但也可循环等解决,不管用什么实 现,其都会遵循深度优先思想。下面是递归实现的程序框架,供初始学习者参考: Procedure DepthFirstSearch(State:Statetype;depth:integer); Begin For Operand:=1 to Operandcount(State) do Begin NewState:=DoOperand(State,Operand); If Answer then PrintAnswer Else if depth<maxdepth then Search(NewState,depth); End; End; 说明:函数名为 DepthFirstSearch。有两个形参 State 和 depth,分别代表初始状态和搜 索的层数。for 语句从 1 开始循环所有能用的算符,循环体里意义是:初始状态上作用一种 算符得到新的状态,随后就判断此状态是否为问题的解,如果是的话就输出之,不是的话 向下递归,以新的状态作为初始状态,层数加 1 做为新的层数开始新的判断。这个框架只 是最简单的,它有很多可以变形。另外,还有一些地方需要注意。 另给出一个 C 的深搜框架: (引自张邦佐老师的课件) void Backtrack(int t) { if(t>n) Output(x); else for(int i=f(n,t);i<=g(n,t);i++) { x[t]=h[i]; if ((Constraint(t)&& Bound(t)) Backtrack(t+1);
宽度优先搜索 BFS 遵循的搜索策略是从源结点开始,把所有该结点的子结点都搜索完,在 搜索每个结点的时候都把其子结点都放入一个队列的后面等待以后搜索,当把此层结点全 部搜索完时,所有的下层结点也就进入了队列,继续这样的过程。当仍然没有找到解并且 还有没有搜索到的结点时,以没有搜索的结点作为源结点继续上述的搜索过程,直至找到 解。 剪枝 在搜索的过程中,在还没到达叶结点之前就可以判断以此结点为根的子树不可能包含 可行解或者最优解,因此不需要扩展这颗树,就像拿一把剪刀把这颗子树剪去,称为剪枝。 还有一些搜索算法的概念没有给出 如分支限界搜索,迭代加深搜索,迭代加宽搜索,A*算 法等。他们都各种有适应的范围,也是较为复杂的搜索。