抱歉最近太忙。。各种出差,难得静下心来研究下,上一篇说到暴力破解,这篇来说说DFS,DFS不明白意思的可以去百度之,简单来说就是从一个节点出发,一直探索与该节点连同的节点,直到走不通为止,然后回退到上一个节点,选择相邻的节点,重复这个过程。有点像走迷宫,碰见一个路口就向左拐,一直走到死胡同,就退一个路口,换一个方向,再一直向左,每次把一个节点连同的都走完,不通就回溯到上一个节点,所以也通常叫做回溯法。
感谢这位大神http://www.cnblogs.com/wuyuegb2312/p/3273337.html,把回溯法讲的灰常透彻,有兴趣的可以仔细看看,回溯法的通用思路就是
/* bool finished = FALSE; //是否获得全部解?
* Dfs(int a[], int k, data input){ //a[]表示当前获得的部分解的集合,k表示搜索的深度,input表示输入
int c[MAXCANDIDATES]; //这次搜索的候选
int ncandidates; // 候选数目
int i; // counter
if (is_a_solution(a,k,input)){//用于判断当前的a[1。。。k]是否是一个可行解
process_solution(a,k,input);//更新到最后的结果里面去,或者直接输出
} else {
construct_candidates(a,k,input,c,&ncandidates);//根据目前状态,构造这一步可能的选择,存入c[]数组,其长度存入ncandidates
for (i=0; i<ncandidates; i++) {
a[k] = c[i];
make_move(a,k,input);//将选择更新到原始的数据结构
backtrack(a,k+1,input);//向下搜索一层
unmake_move(a,k,input);//将选择撤回,也就是回溯的过程
if (finished){
return; // 如果符合终止条件就提前退出
}
}
}
}*/
下面是练习,问题1:求一个集合的所有子集,思路:最大深度就是集合元素的个数,对于每次搜索,下一个位置只可能有两种情况,包括或者不包括
public static void Dfs1(int a[],int deep,int[] input){
int c[] = {0,1};
int ncandidates = 2;
if(deep == input.length){
System.out.print(“{“);
for(int i=0;i<deep;i++){
if(a[i] == 1){
System.out.print(input[i]+” “);
}
}
System.out.print(“}\n”);
} else{
for(int i=0;i<ncandidates;i++){
a[deep] = c[i];
Dfs1(a,deep+1,input);
}
}
}
问题2,:八皇后问题,8*8的格子放入8个皇后,使得所有皇后不在一行一列且不在对角线,
思路:套用框架,每次判断下一个位置是否符合条件,然后回溯
public static void Dfs2(int deep , int[][] input , int[] candidates){
if(deep == 8){
for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
System.out.print(input[i][j]);
}
System.out.print(“\n”);
}
System.out.print(“\n”);
}else{
for(int i=0;i<8;i++){
if(candidates[i]==1 || IsCollision(input,deep,i)){
continue;
}else{
input[deep][i] = 1;
candidates[i] = 1;//用于剪枝,每当有一个位置被选中,整列都不能再被选择
Dfs2(deep+1,input,candidates);
input[deep][i] = 0;
candidates[i] = 0;
}
}
}
}
public static boolean IsCollision(int[][] input,int x,int y){
int i,j;
for(i=0;i<x ;i++){//没有横着的
if(input[i][y] == 1){
return true;
}
}
for(j=0;j<y;j++){//没有竖着的
if(input[x][j] == 1){
return true;
}
}
if(x == y){//没有左对角线的
return true;
}
if(x + y == 7){//没有右对角线的
return true;
}
return false;
}
框架确实很犀利很强大。。。这个才是算法的精髓所在吧,一法在手,多题我有~~~下一篇就是用DFS来解决邮票问题咯~~