北大ACM1010-深度优先搜索(DFS)初探

抱歉最近太忙。。各种出差,难得静下心来研究下,上一篇说到暴力破解,这篇来说说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来解决邮票问题咯~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值