DFS剪枝初步

剪枝经典例题:
Tempter of the Bone http://acm.hdu.edu.cn/showproblem.php?pid=1010
题目描述: 一个迷宫有N*M格,有一些格子是地板能走,有一些格子是障碍不能走。给一个起点S和一个终点D。一只小狗从S出发,每步走一块地板,在每个地板不能停留,而且走过的地板都不能再走。给定一个T,问小狗能正好走T步到达D吗?
输入输出:有很多测试样例,每个测试中,第1行是整数N,M,T, 1 < N, M < 7, 0 < T < 50。后面有N行,每行M个字符,有这些字符:‘X’: 墙;‘S’: 起点;‘D’: 终点;’.’: 地板。最后一行是’0 0 0’,表示结束。如果狗能逃出,输出YES,否则输出NO。
输入输出样例:
输入
4 4 5
S.X.
…X.
…XD

3 4 5
S.X.
…X.
…D
0 0 0
输出
NO
YES。

题解:对于路径问题应该用DFS,对于这题采用奇偶剪枝。
奇偶方块图
曼哈顿距离f=abs(c−x)+abs(d−y),如果S和D的曼哈顿距离f是奇数,说明S和D一个是0一个是1;如果f是偶数,说明S和D同0或同1。对于此题,如果T−f是奇数则肯定无解,因为T和f必须同奇或同偶。
代码:

#include <bits/stdc++.h>
using namespace std;
char mat[8][8],visit[8][8];
int n, m, t;
int flag;           //flag=1,表示找到了答案
int a, b, c, d;     //起点S(a,b),终点D(c,d)
int dir[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}};        //上下左右4个方向
#define CHECK(xx,yy) (xx>=0 && xx<n && yy>=0 && yy<m)  //是否在迷宫中

void dfs(int x, int y, int time){     
    if(flag)  return;                   //逐层退出DFS,有多少层DFS,就退多少次
    
    if(mat[x][y] == 'D'){        
        if(time == t)    flag = 1;      //找到答案
        return;                         //D只能走一次,所以不管对不对,都返回   
    }    
    //if(time > t)     return;          //剪枝(1):因为有剪枝(2),(1)就多余了

    int tmp = t - time - abs(c-x) - abs(d-y);
    if(tmp < 0)     return;             //剪枝(2)
    
    for(int i=0; i<4; i++){             //上下左右
        int xx = x + dir[i][0], yy = y + dir[i][1];
        if(CHECK(xx,yy)  && mat[xx][yy]!='X' && !visit[xx][yy]){      
            visit[xx][yy] = 1;          //地板标记为走过,不能再走        
            dfs(xx, yy, time + 1);      //遍历所有的路径
            visit[xx][yy] = 0;          //递归返回,这块地板恢复为没走过
        }
    }    
    return;
}
int main(){
    while(~scanf("%d%d%d",&n,&m,&t)){
        if(n==0 && m==0 && t==0)    break;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                cin>>mat[i][j];
                if(mat[i][j] == 'S') a=i,b=j;
                if(mat[i][j] == 'D') c=i,d=j;
            }
        memset(visit, 0, sizeof(visit));
        int tmp = t - abs(c-a) - abs(d-b);  //在DFS之前,做奇偶判断
        if(tmp & 1){                        //无解,不用DFS了
            puts("NO"); 
            continue;
        }
        flag = 0;
        visit[a][b] = 1;                    //标记起点已经走过
        dfs(a, b, 0);                       //搜索路径
        
        if(flag) puts("YES");
        else     puts("NO");
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DFS(深度优先搜索)是一种常见的图遍历算法,它使用递归或栈的方式,从一个顶点出发,沿着一条路径一直到达最深的节点,然后回溯到上一层继续遍历其他节点。DFS常被用于解决图的连通性问题、路径问题等。在实际应用中,可以使用DFS进行状态搜索、图的遍历、拓扑排序等。 剪枝是指在搜索过程中,通过一系列的策略判断,提前终止当前搜索分支,并跳过一些无用的搜索路径,从而减少搜索时间。剪枝的核心在于提前排除某些明显不符合条件的状态,以减少无效搜索的时间开销,提高效率。在算法设计中,剪枝通常会利用一些特定的性质或条件进行判断,从而缩小搜索空间。 动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划通常用于求解最优化问题,它通过定义状态和状态转移方程,采用自底向上的思路,逐步求解每个子问题的最优值,最终得到原问题的最优解。动态规划的核心是存储已经计算过的子问题的解,避免了重复计算。 贪心算法是一种基于局部最优解的策略,它通过每一步选择在当前状态下最优的解,以期望得到全局最优解。贪心算法的基本思想是由局部最优解推导出全局最优解,通常通过贪心选择性质、最优子结构和贪心选择构成三部分。贪心算法相比其他算法,如动态规划,它的优势在于简单、高效,但缺点在于不能保证获取到全局最优解,只能得到一个近似解。 综上所述,DFS剪枝、动态规划和贪心算法算法设计和问题求解中都发挥着重要的作用。具体使用哪种算法取决于问题的性质和要求,需要在实际应用中进行综合考虑和选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值