1. 程式人生 > >poj 3009 冰球 【DFS】求最小步數

poj 3009 冰球 【DFS】求最小步數

同步 IV ret AI 失敗 ios 並不會 size \n

題目鏈接:https://vjudge.net/problem/POJ-3009

轉載於:https://blog.csdn.net/angon823/article/details/49910109

題目大意:

要求把一個冰壺從起點“2”用最少的步數移動到終點“3”,其中0為移動區域,1為石頭區域,冰壺一旦想著某個方向運動就不會停止,也不會改變方向(想想冰壺在冰上滑動),除非冰壺撞到石頭1 或者 到達終點 3

需要註意的是:

冰壺撞到石頭後,冰壺會停在石頭前面,此時(靜止狀態)才允許改變冰壺的運動方向,而該塊石頭會破裂,石頭所在的區域由1變為0. 也就是說,冰壺撞到石頭後,並不會取代石頭的位置。

終點是一個摩擦力很大的區域,冰壺若到達終點3,就會停止在終點的位置不再移動。並且,如果步數>1,則直接算失敗,這條dfs搜索路徑直接舍棄。

解題分析:
這裏用了dfs來求最小步數,求出所有能夠到終點的解,然後用它們不斷去更新步數的最小解。下列代碼中,用whlie循環來代替它向一個方向走的不同步數,如果能夠向前滑行,則while循環繼續執行。

#include <iostream>  
#include <stdio.h>  
#include <string.h>  
#include <algorithm>
using namespace std;
int map[25][25], m, n, sx, sy;
int dir[][2] = { 1,0,-1,0,0,1,0,-1 };
int ans; void dfs(int x, int y, int step) { int nx, ny, ex, ey; //(nx,ny) 代表下一步 (ex,ey) 代表走的這一步 if (step>10)return; //實際上是剪枝 for (int i = 0; i<4; i++) //向四個方向走 { nx = x + dir[i][0]; //下一步 ny = y + dir[i][1]; ex = x;ey = y; while (nx >= 0
&& nx<m && ny >= 0 && ny<n && map[nx][ny] != 1) //為真則代表這個方向能走,因為冰球緊貼冰塊的那個方向不能走 { ex += dir[i][0]; //則走這一步 ey += dir[i][1]; if (map[ex][ey] == 3) //走的這步是終點嗎。 { ans = min(ans, step); return; } nx = ex + dir[i][0]; //走完這一步的下一步 ny = ey + dir[i][1]; if (nx<0 || nx >= m || ny<0 || ny >= n) break; //如果下一步是越界,說明會直接滑出去,不必再進行dfs if (map[nx][ny] == 1) //如果下一步是1,進行深搜. { map[nx][ny] = 0; dfs(ex, ey, step + 1); map[nx][ny] = 1; } //如果下一步還是0,按照題意,當然要繼續滑下去,繼續while,循環前進 } } } int main() { while (~scanf("%d %d", &n, &m), m || n) { for (int i = 0; i<m; i++) for (int j = 0; j<n; j++) { scanf("%d", &map[i][j]); if (map[i][j] == 2) { sx = i; sy = j; } } ans = 0x3f3f3f3f; dfs(sx, sy, 1); if (ans == 0x3f3f3f3f) printf("-1\n"); else printf("%d\n", ans); } return 0; }

2018-05-27

poj 3009 冰球 【DFS】求最小步數