HDU 1010 dfs 奇偶剪枝
2017-08-22 00:00
253 查看
题意:根据地图,'S'为开始位置,'D'为门的位置,' . '为空地,'X'为墙,不能经过,
问:在指定的时间,是否能到达'门'的位置.
注意:路不可以重复经过,时间也要刚好是 t ,不能少.
思路:还是DFS,不能用BFS,因为BFS求的是最短路径,而此题的路径不一定最短.
剪枝是关键,奇偶剪枝.
奇偶剪枝原理:
要理解奇偶剪枝,先了解一下曼哈顿距离,从一个点到达另外一个点的最短路径长度(时间)可以根据两点坐标求出,
路径长度(非最短)与最短路径的长度同奇偶,它们的差一定是偶数!举个例子,就像两个偶数的差差是偶数,两个个数的差也是偶数.
本题还有一个剪枝:n*m-wall与t的关系,wall为'X'的数量,解释一下,n*m为区域总数,
所以m*n-wall<=t 一定不到到达终点,注意,少时等号在杭电上运行时间为546MS,而加上等号运行时间才为78MS!
eg:
3 3 4
SXX
.XX
X.D
上面的例子满足m*n-wall=t,确实不能到达,但不能找到合理的解释......
奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
70
奇偶剪枝
设起点s的坐标为(sx,sy),终点e的坐标为(ex,ey);
对s的一次操作为对sx或sy进行+1或-1;
若经过t次操作后,s的坐标刚好等于e,则说从s经过t步可以到达e。
在理想情况下,s到e需要的最小步数为m
m=|ex-sx|+|ey-sy|
若t<m,肯定是无法到达的。
当t>=m时,从s到e的行走路径由两部分组成,
一部分为需要走的最少步数m;
另一部分是为了使得刚好行走t步到达e,所需要走的附加步数a,a=t-m;
这a步即为:从需要走m步的最短路径上走出去,再回到最短路径上所走的步数。
假设走出去这段路径长度为b,那回来时的路径长度一定也是b,因此,附加步数的路径长度a等于2b步。
因为走出去时,对坐标进行了b次+1或-1的操作,为使坐标再恢复到最短路径上,就需要进行b次-1或+1的操作,并且与走出去时是相反的。注意:走出去和拐回来的过程中可能参杂着最短路径上的操作,所以b是除去这些参杂操作后的步数。
如下图所示:
从s到e的黑色路径为一条最短路径,红色和蓝色路线组成的路径,为走出最短路径的路径。其中蓝色箭头是参杂着的最短路径中的操作,只有红色箭头才是走出去和拐回来的路径,如果将红色路径去掉,从s向右走,经过绿色箭头到达e,这也是一条最短路径。
因为a=2b,是个偶数,又因为a=t-m,所以当t和m的奇偶性相同时,a才能是偶数。也就是说,当t和m的奇偶性相同时,才有可能从s经过t步,到达e。
所以,当最小步数m与t同为奇数,或同为偶数时,才有可能从s经过t步,到达e
最小距离和绕路距离同奇偶
奇偶剪枝 TLE->500
路径长度 剪枝 500->50
50
问:在指定的时间,是否能到达'门'的位置.
注意:路不可以重复经过,时间也要刚好是 t ,不能少.
思路:还是DFS,不能用BFS,因为BFS求的是最短路径,而此题的路径不一定最短.
剪枝是关键,奇偶剪枝.
奇偶剪枝原理:
要理解奇偶剪枝,先了解一下曼哈顿距离,从一个点到达另外一个点的最短路径长度(时间)可以根据两点坐标求出,
路径长度(非最短)与最短路径的长度同奇偶,它们的差一定是偶数!举个例子,就像两个偶数的差差是偶数,两个个数的差也是偶数.
本题还有一个剪枝:n*m-wall与t的关系,wall为'X'的数量,解释一下,n*m为区域总数,
所以m*n-wall<=t 一定不到到达终点,注意,少时等号在杭电上运行时间为546MS,而加上等号运行时间才为78MS!
eg:
3 3 4
SXX
.XX
X.D
上面的例子满足m*n-wall=t,确实不能到达,但不能找到合理的解释......
奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
70
// http ://acm.hdu.edu.cn/showproblem.php?pid=1010 // 大致题意:给一幅图,有起点有墙有终点,问能不能在刚好t秒的时间走到终点 // DFS + 多重剪枝(奇偶性剪枝) // 一开始果断DFS,交上去TLE了。。。用了好几重的剪枝才过。。。。 // 所以不要小看剪枝,往往优化个成百上千倍 #include <iostream> #include <cmath> using namespace std; char map[10][10]; int flag, Xnum, Sx, Sy, Dx, Dy; int n, m, t; int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; void DFS(int x, int y, int time){ if (x <= 0 || x > n || y <= 0 || y > m) return; if (flag == 1) return; //1.马上中断 if (x == Dx && y == Dy && time == t){ if (time == t) flag = 1; return; } int temp = (t - time) - abs(x - Dx) - abs(y - Dy);//2.奇偶性剪枝 if (temp < 0 || temp & 1) return; for (int i = 0; i < 4; i++){ int x1 = x + dir[i][0]; 7fe8 int y1 = y + dir[i][1]; if (map[x1][y1] != 'X'){ map[x1][y1] = 'X'; DFS(x1, y1, time + 1); map[x1][y1] = '.'; } } return; } int main(){ while (cin >> n >> m >> t){ if (n == 0 && m == 0 && t == 0) break; Xnum = 0; for (int i = 1; i <= n; i++){ for (int j = 1; j <= m; j++){ cin >> map[i][j]; if (map[i][j] == 'S'){ Sx = i; Sy = j; } if (map[i][j] == 'D'){ Dx = i; Dy = j; } if (map[i][j] == 'X') Xnum++; } } flag = 0; map[Sx][Sy] = 'X'; if (n * m - Xnum <= t){//3.提前判断t过大的情况避免再去搜,写上由500MS降到46MS printf("NO\n"); continue; } DFS(Sx, Sy, 0); printf("%s",flag?"YES\n":"NO\n" ); } return 0; }
奇偶剪枝
设起点s的坐标为(sx,sy),终点e的坐标为(ex,ey);
对s的一次操作为对sx或sy进行+1或-1;
若经过t次操作后,s的坐标刚好等于e,则说从s经过t步可以到达e。
在理想情况下,s到e需要的最小步数为m
m=|ex-sx|+|ey-sy|
若t<m,肯定是无法到达的。
当t>=m时,从s到e的行走路径由两部分组成,
一部分为需要走的最少步数m;
另一部分是为了使得刚好行走t步到达e,所需要走的附加步数a,a=t-m;
这a步即为:从需要走m步的最短路径上走出去,再回到最短路径上所走的步数。
假设走出去这段路径长度为b,那回来时的路径长度一定也是b,因此,附加步数的路径长度a等于2b步。
因为走出去时,对坐标进行了b次+1或-1的操作,为使坐标再恢复到最短路径上,就需要进行b次-1或+1的操作,并且与走出去时是相反的。注意:走出去和拐回来的过程中可能参杂着最短路径上的操作,所以b是除去这些参杂操作后的步数。
如下图所示:
从s到e的黑色路径为一条最短路径,红色和蓝色路线组成的路径,为走出最短路径的路径。其中蓝色箭头是参杂着的最短路径中的操作,只有红色箭头才是走出去和拐回来的路径,如果将红色路径去掉,从s向右走,经过绿色箭头到达e,这也是一条最短路径。
因为a=2b,是个偶数,又因为a=t-m,所以当t和m的奇偶性相同时,a才能是偶数。也就是说,当t和m的奇偶性相同时,才有可能从s经过t步,到达e。
所以,当最小步数m与t同为奇数,或同为偶数时,才有可能从s经过t步,到达e
最小距离和绕路距离同奇偶
奇偶剪枝 TLE->500
路径长度 剪枝 500->50
50
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <queue> #define LL long long int const MAX = 1e6 + 1; int const INF = 1 << 30; double const EPS = 0.00000001; using namespace std; int n, m, p, xnum; int g[10][10]; int stx, sty, edx, edy; int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0}; bool flag; char s[11]; void dfs(int x, int y, int step){ if (step > p || flag == 1) return; if (x == edx && y == edy && step == p){ flag = 1; return; } int mindis = abs(x - edx) + abs(y - edy); //步数不够,或者奇偶性不对 if (mindis > p - step || ((mindis + p - step) & 1)) return; for (int i = 0; i < 4; i++){ int nx = x + dir[i][0], ny = y + dir[i][1]; if (g[nx][ny]){ g[nx][ny] = 0; dfs(nx, ny, step + 1); g[nx][ny] = 1; } } } int main(){ freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); while (scanf("%d%d%d", &n, &m, &p) == 3 && n + m + p){ xnum = 0; flag = 0; memset(g, 0, sizeof(g)); for (int i = 1; i <= n; i++){ scanf("%s", s); for (int j = 1; j <= m; j++){ g[i][j] = (s[j - 1] == 'X' ? 0 : 1); if (s[j - 1] == 'S') stx = i, sty = j; if (s[j - 1 ] == 'D') edx = i, edy = j; if (s[j - 1] == 'X') xnum++; } } // for (int i = 0; i < n; i++) // printf("%s\n", g[i]); // g[0]表示不可以走 g[stx][sty] = 0; //最小步数不够到达目标点,走n步,需要n+1块可以走的格子 if (xnum >= (n * m) - p) printf("NO\n"); else { dfs(stx, sty, 0); printf("%s", flag ? "YES\n" : "NO\n"); } } return 0; }
相关文章推荐
- hdu 1010 Tempter of the Bone(dfs+奇偶剪枝)
- HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
- hdu 1010 Tempter of the Bone(DFS + 奇偶剪枝 + 路径剪枝)
- 【HDU 1010】Tempter of the Bone(DFS,奇偶剪枝)
- HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
- HDU 1010 Tempter of the Bone - (DFS) 奇偶剪枝
- HDU 1010 Tempter of the Bone (DFS+奇偶剪枝,一个起点一个终点)
- HDU 1010 ZOJ 2110 Tempter of the Bone (DFS 奇偶剪枝)
- hdu 1010:Tempter of the Bone(DFS + 奇偶剪枝)
- 4000 HDU 1010 - Tempter of the Bone(DFS 奇偶剪枝)
- HDU 1010 && ZOJ 2110 Tempter of the bone (DFS + 奇偶剪枝)
- HDU 1010 Tempter of the Bone(DFS,奇偶剪枝)
- HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
- HDU 1010 Tempter of the Bone( DFS + 奇偶剪枝 )
- HDU 1010 Tempter of Bone DFS + 奇偶剪枝
- HDU 1010 (DFS搜索+奇偶剪枝)
- HDU 1010 dfs+奇偶剪枝
- hdu 1010 Tempter of the Bone(dfs+奇偶剪枝)
- HDU 1010 Tempter of the Bone (DFS+奇偶剪枝)
- HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)