HDU - 1010 (DFS回溯法 + 奇偶剪枝)

题目大意:给出一个N*M的迷宫,迷宫中有一扇门D,只有在T时刻会打开,现在你0时刻位于S,你需要在正好在T时刻到达D,你只能上下左右移动,每次移动耗费1时刻,且同一个位置不能进入两次,问是否能在T时刻刚好到达D处。

范围 1 < N,M < 7, 1 < T < 50,这个范围有点大,直接DFS回溯搜会TLE,我们要加上一个剪枝,这个剪枝十分重要,我们求出起点到终点的距离(横向距离 + 纵向距离),若这个距离为奇数,则时间T必须也要为奇数,否则时间T必须为偶数(其中的道理显而易见),只有这样,你才有可能在T时刻到达D。详情见下面的代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <queue>
 7 #include <stack>
 8 using namespace std;
 9
10 typedef long long LL;
11 typedef unsigned long long ULL;
12 const int dx[] = {1,-1,0,0};
13 const int dy[] = {0,0,1,-1};
14
15 int N, M, T, bx, by, ex, ey;
16 char Map[10][10];
17 int vis[10][10];
18
19 bool dfs(int x, int y, int t){
20     if(x == ex && y == ey && t == T) return true;
21     if(t >= T) return false;
22     for(int i = 0; i < 4; ++i){
23         int nx = x + dx[i];
24         int ny = y + dy[i];
25         if(nx >= 0 && ny >= 0 && nx < N && ny < M){
26             if(vis[nx][ny]) continue;
27             if(Map[nx][ny] == ‘X‘) continue;
28             vis[nx][ny] = 1;
29             if(dfs(nx, ny, t+1)) return true;
30             vis[nx][ny] = 0;
31         }
32     }
33     return false;
34 }
35
36 int main(){
37     while(scanf("%d%d%d", &N, &M, &T) == 3 && N){
38         for(int i = 0; i < N; ++i){
39             scanf("%s", Map[i]);
40             for(int j = 0; j < M; ++j)
41                 if(Map[i][j] == ‘D‘) {
42                     ex = i;
43                     ey = j;
44                 }else if(Map[i][j] == ‘S‘) {
45                     bx = i;
46                     by = j;
47                 }
48         }
49
50         //奇偶剪枝
51         int dis = abs(bx-ex)+abs(by-ey);
52         if(dis%2 != T%2) {
53             printf("NO\n");
54             continue;
55         }
56
57         memset(vis, 0, sizeof(vis));
58         vis[bx][by] = 1;
59         if(dfs(bx, by, 0)) printf("YES\n");
60         else printf("NO\n");
61     }
62     return 0;
63 }

原文地址:https://www.cnblogs.com/DynastySun/p/9436456.html

时间: 2024-08-01 02:36:25

HDU - 1010 (DFS回溯法 + 奇偶剪枝)的相关文章

HDU 1010 Tempter of the Bone【DFS经典题+奇偶剪枝详解】

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 125945    Accepted Submission(s): 33969 Problem Description The doggie found a bone in an ancient maze, which fascinated him a

HDU 1015 dfs回溯

题目真长.....看了好长时间才看懂.. 就是给你一个32位数字和一个最多15个字符的字符串,从字符串中选出5个字符,若满足题中给的那个式子,输出字典序最大的那5个字符,若不满足,输出no solution. 为了解决字典序问题,在输入字符串后,把字符串按从大到小排一下序,搜索一下若满足条件输出即可. 贴代码. 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <

hdu 1010 dfs+剪枝

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 119601 Accepted Submission(s): 32313 Problem Description The doggie found a bone in an ancient maze, which fascinated him a lot.

UVA - 524 Prime Ring Problem(dfs回溯法)

UVA - 524 Prime Ring Problem Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description A ring is composed of n (even number) circles as shown in diagram. Put natural numbers  into each circle separately, and the sum of number

hdu 1010 dfs搜索

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 107138    Accepted Submission(s): 29131 Problem Description The doggie found a bone in an ancient maze, which fascinated him a

hdu 4155 dfs回溯

数据并不大,dfs回溯即可. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 30; 7 char str[N]; 8 int digit[N]; 9 10 int dfs( int sum ) 11 { 12 if ( sum > 31 ) return 1; 13 for ( int i = 1; i

DFS中的奇偶剪枝学习笔记

奇偶剪枝学习笔记 描述 编辑 现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点, s | | | + — — — e 如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8: s — — — — — + | + | + — — — e 如图,为一般情况下非最短路径的任意走法举例,step2=14: step2-step1=6,偏移路径为6,偶数(易证): 结

hdoj 1010 Tempter of the Bone 【DFS】+【奇偶剪枝】

题意:从S出发到D停止,并且要在指定的时间t走到(不早不晚).注意,每个'.'只能走一次. 分析:DFS,但是用普通的dfs,TL, 所以要剪枝.我们可以想到,如果可以早到D点,但是D点周围有其他可以踩的点,并且可以观察到,从一个点(不是D点)到D点的距离(abs(x-dx)+abs(y-dy))是奇数的话,就要走奇数步,偶数的就走偶数步,() 代码: #include <stdio.h> #include <string.h> #include <stdlib.h>

hdu 1010 dfs 走到终点时刚好花掉所有时间 奇偶性剪枝

题意:输入一个n*m的迷宫,和一个T:可以在迷宫中生存的最大时间.S为起点,D为终点.并且,每个格子只能踩一次,且只能维持一秒,然后该块地板就会塌陷.所以你必须每秒走一步,且到D点时,所用时间为T.用深搜.奇偶性剪枝:如果当前的狗所在的坐标与D的坐标奇偶性不一样,那么狗需要走奇数步.同理,如果狗所在坐标与D的坐标奇偶性一样,那么狗需要走偶数步数. 也就是说,狗的坐标x.y和对2取余是它的奇偶性,Dxy和对2取余是D的奇偶性.两个奇偶性一加再对2取余,拿这个余数去与剩下时间对2取余的余数作比较即可