HDU 1010 Tempter of the Bone

[url]http://acm.hdu.edu.cn/showproblem.php?pid=1010[/url]

[size=medium]题意:给出T,问第T秒是否能从S去到D

[color=blue]Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0

Sample Output
NO
YES

这题有2个重要的剪枝要学习[/color][/size]

[size=medium]剪枝前后对比
第一个是删掉奇偶剪枝后的情况
第二个是删掉步数剪枝后的情况
[/size][img]http://dl.iteye.com/upload/attachment/492287/bcb455a4-e1d4-3329-9454-8f7c8bf2e5b1.jpg[/img]



#include <iostream>
using namespace std;

char map[8][8];
int r, c, ttime, x2, y2; //ttime 是所给时间T,【r:行、c:列】
bool flag; //x2、y2是终点坐标
int x_move[4] = {0, 1, -1, 0};
int y_move[4] = {1, 0, 0, -1};

void dfs (int x, int y, int t) //t是走到当前坐标时的时刻
{
if (t > ttime) //超时
return ; //下面的tmp的意义:【剩余时间(ttime - t)(记为left)】与【从当前坐标走到终点所需时间( abs(x-x2) + abs(y-y2) )(记为win)】的差,如果tmp是奇数,说明left与win的奇偶性不同!也就是说在第T秒时,不可能从当前坐标走到终点!
int tmp = ttime - t - abs(x-x2) - abs(y-y2);
if (tmp < 0 || tmp & 1) //奇偶剪枝,非常重要,很抽象 Orz...
return ;
for (int i = 0; i < 4; i++)
{
int tx = x + x_move[i];
int ty = y + y_move[i];
if (tx < 0 || ty < 0 || tx >= r || ty >= c)
continue;
if (map[tx][ty] == 'D' && t + 1 == ttime)//到达终点且该时刻t+1为所给时间,即成功到达
{
flag = true;
return ;
}
if (map[tx][ty] == '.')
{
map[tx][ty] = 'X'; //已走格子变成墙,根据题意,已走格子不可再走
dfs (tx, ty, t+1);
if (flag) //成功
return ;
map[tx][ty] = '.'; //回溯
}
}
}
int main()
{
int i, j, x1, y1, empty;
while (scanf ("%d%d%d", &r, &c, &ttime) != EOF)
{
if (!r && !c && !ttime)
break;
empty = 0;
for (i = 0; i < r; i++)
{
scanf ("%s", map[i]);
for (j = 0; j < c; j++)
{
if (map[i][j] == 'S') //找到起点的坐标
x1 = i, y1 = j;
if (map[i][j] == 'D') //找到终点的坐标
x2 = i, y2 = j;
if (map[i][j] == '.') //计算总的可能行走的步数
empty++;
}
}
if (empty + 1 < ttime) //步数剪枝,常识,可行步数小于总时间,在T时刻肯定不可走到终点
{
puts ("NO");
continue;
}
flag = false;
dfs (x1, y1, 0);
if (flag)
puts ("YES");
else puts ("NO");
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值