DFS中的奇偶剪枝
本博客由搜集资料拼凑而成。。。
首先介绍什么是奇偶剪枝:
奇偶剪枝
【问题描述:】
给定一个N*M的迷宫以及起点和终点,迷宫中有一些障碍无法穿过,问能否不重复也不停留地在刚好一共走T步出迷宫。
【问题分析:】
先来看下这张图片:
也就是说当要走偶数步而规定的步数是奇数,或者要走奇数步而规定的步数是偶数,都是不可能到达的,如果要想到达,则要走的步数和规定的步数的奇偶性应该一致。又可知,奇偶性一致的两个数的差或者和都是偶数。(下面有大用处)
例如下图:设S点坐标为(sx,sy),D点坐标为(dx,dy),.表示通路,X表示障碍。
S...
....
....
...D
可知从S走到D的最短距离为abs(sx-dx)+abs(sy-dy);
S..X
..XX
.X.X
...D
上面这个迷宫中存在一些障碍,假设当前已走step步,则还剩下t-step步,设当前点到终点的最短距离为abs(si - dx)+ abs(sj - dy),则两者的奇偶性一定一致的(由上面那段话可知)并且前者一定大于等于后者(剩下要走的步数大于等于该坐标到终点的最短距离),只有这样,才能够到达。也就是tem = t – step – (abs(si - dx)+ abs(sj - dy)),tem >= 0 && tem % 2 == 0.
(http://blog.csdn.net/i1020/article/details/54918472)其中奇偶剪枝关键便是这句话
ans = t - step - abs(x-ex)-abs(y-ey);
if(ans<0||ans&1)return;
//t为限制的步数,step为已经走过的步数,x,y当前位置
//ex,ey为终点位置
例题:
Tempter of the Bone(HDU-1010)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.
The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
The input is terminated with three 0's. This test case is not to be processed.
Output
For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
NO
YES
题意:在一个坐标内,给定起点和终点,问能否恰好在t时刻到达终点。
一开始直接搜索超时,后来各种剪枝还是超时,就单单没有判断奇偶性。判断后又忘记每次初始化访问数组,错了很多次
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n,m,t;//n,m数组大小,t限制时间
char mp[20][20];//地图
int vis[20][20];//访问数组
int solve;//判断能否到达的变量
int sx,sy,ex,ey;//起点坐标,终点坐标
int dirx[4] = {0,0,1,-1};
int diry[4] = {1,-1,0,0};//方向数组
void dfs(int x,int y,int s){
int i;
int xx,yy;
if(x==ex&&y==ey&&s==t){
solve = 1;
return;
}//恰好符号条件就将solve变成1
int ans = t-s-abs(x-ex)-abs(y-ey);
if(ans&1||ans<0)return;//奇偶剪枝
//if(s>=t)return;
if(solve==1)return;//如果发现之前已经符合条件了,就直接返回就可以
for(i = 0; i < 4; i++){
xx = x + dirx[i];
yy = y + diry[i];
if(xx>=0&&xx<n&&yy>=0&&yy<m&&vis[xx][yy]==0&&mp[xx][yy]!='X'){
vis[xx][yy] = 1;
dfs(xx,yy,s+1);
vis[xx][yy] = 0;//普通DFS
}
}
}
int main(){
int i,j;
while(~scanf("%d%d%d",&n,&m,&t)){
if(n==0&&m==0&&t==0)break;
solve = 0;
for(i = 0; i < n; i++)
scanf("%s",mp[i]);
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){
if(mp[i][j]=='S'){
sx = i;
sy = j;
}
if(mp[i][j]=='D'){
ex = i;
ey = j;
}//记录始末位置
}
}
if(abs(sx-ex)+abs(sy-ey)<=t){//判断如果从起点到终点的最短距离都比t大说明一定到达不了,所以进行判断以优化
memset(vis,0,sizeof(vis));
vis[sx][sy] = 1;
dfs(sx,sy,0);
}
if(solve)
printf("YES\n");
else printf("NO\n");
}
return 0;
}
推荐阅读
-
【每日一道算法题】Leetcode之longest-increasing-path-in-a-matrix矩阵中的最长递增路径问题 Java dfs+记忆化
-
双指针法-删除数组中的重复元素以及奇偶排序
-
DFS中关于全排列、组合、子集中有重复数字去重的问题
-
Python代码实现找到列表中的奇偶异常项
-
//将数组中的元素是五的倍数的元素输出到下拉菜单 //将数组中的元素放在
- 标签中,奇偶li背景不同 //将数组中元素是数字型的找出来
-
DOM中BFS(广度优先遍历)和DFS(深度优先遍历)的方法
-
对于dfs剪枝的分析
-
DFS---奇偶剪枝
-
LeetCode 1367. 二叉树中的列表(二叉树的遍历、DFS)
-
【HDU 1010】顺序刷题 Tempter of the Bone (dfs 奇偶剪枝)