HDU1010(回溯剪枝)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010

一. 题意:

小狗从S出发,1s跳一个格子,Ts后恰好跳到D,不可以跳跳过的格子。问是否跳得出去。


二. 易错点:

我要先发图!


1. 要记得剪枝。

2. 在判断是否到达门的时候,最好用坐标,因为用maze[i][j] == 'D'的话。

首先你要记得判断后再把它置为 ‘X’ 

其次也是致命的,如果门那里回溯过一次的话,你会把它变为 ‘.’ ,这样的话下次再找到那里就失效了,有人会说设一个标志,当时你判断是否进去怎么办?就是这个找出来的我就AC了哈哈哈哈哈哈哈!虽然600多ms险过。


三. 知识预备

1. 奇偶剪枝:

从S到D,最短路径minPath = abs(iStart - iEnd) + abs(iStart + iEnd)

如果要绕道的话,绕过的道一定为偶数,因为要出去再返回到原道路上。

因此可以用总时间T减去最短路径,那么就可以得到偏离的道路,如果不是偶数直接剪枝。

而且把剪枝放在外面,因为放在DFS里面完全没有意义,想一下走一下你的时间就减少1s。然后你再用剩下的时间去判断有什么意义,不是跟走之前判断一个结果吗。只是徒增你的栈空间。

2. 位运算判断奇偶性

纯属装X技巧:计算机用二进制表示整型数。跟1进行&运算,如果最后一位是1,说明是奇数,计算后结果为1。如果最后一位是0,说明是偶数。计算后结果为0。听说位运算速度快哦!(虽然也听说微观优化你绝对比不过编译器)


四. 贴代码啦啦啦

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>

using namespace std;

char maze[8][8];
int N, M, T, iStart, jStart, iEnd, jEnd, cou;

bool check(int i, int j)
{
   if(i < 0 || i >= N || j < 0 ||
      j >= M ||'X' == maze[i][j])
        return false;
   else
        return true;
}

int movei[4] = {-1, 0, 1, 0};
int movej[4] = {0, -1, 0, 1};

bool dfs(int i, int j)
{

    int minPath = abs(iEnd - i) + abs(jEnd - j);

    if(T - cou < minPath)
        return false;

    if(i == iEnd && j == jEnd && cou == T){       //Attention: You can't use "maze[i][j] == 'D' here
        return true;
    }

    maze[i][j] = 'X';
    int m;

    for(m = 0; m < 4; m++){
        if(check(i + movei[m], j + movej[m])){
            cou++;
            if(dfs(i + movei[m], j + movej[m]))
                return true;
            cou--;
            maze[i + movei[m]][j + movej[m]] = '.';
        }
    }

    return false;
}

int main()
{
    //freopen("in.txt", "r", stdin);

    int i, j;

    while(1){
        cin>>N>>M>>T;

        cou = 0;

        if(!N && !M && !T)
            break;

        for(i = 0; i < N; i++)
                cin>>maze[i];

        for(i = 0; i < N; i++)
            for(j = 0; j < M; j++){
            if('S' == maze[i][j]){
                iStart = i;
                jStart = j;
            }
            if('D' == maze[i][j]){
                iEnd = i;
                jEnd = j;
            }
        }
        int minPath = abs(iStart - iEnd) + abs(jStart - jEnd);

        if((T - minPath) & 1){
            cout<<"NO\n";
        }
        else if(dfs(iStart, jStart))
            cout<<"YES\n";
        else
            cout<<"NO\n";
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值