HDOJ1728 逃離迷宮 DFS 剪枝

2021-08-28 11:51:58 字數 3258 閱讀 2368

題目鏈結 

problem description

給定乙個m × n (m行, n列)的迷宮,迷宮中有兩個位置,gloria想從迷宮的乙個位置走到另外乙個位置,當然迷宮中有些地方是空地,gloria可以穿越,有些地方是障礙,她必須繞行,從迷宮的乙個位置,只能走到與它相鄰的4個位置中,當然在行走過程中,gloria不能走到迷宮外面去。令人頭痛的是,gloria是個沒什麼方向感的人,因此,她在行走過程中,不能轉太多彎了,否則她會暈倒的。我們假定給定的兩個位置都是空地,初始時,gloria所面向的方向未定,她可以選擇4個方向的任何乙個出發,而不算成一次轉彎。gloria能從乙個位置走到另外乙個位置嗎?

input

第1行為乙個整數t (1 ≤ t ≤ 100),表示測試資料的個數,接下來為t組測試資料,每組測試資料中,

第1行為兩個整數m, n (1 ≤ m, n ≤ 100),分別表示迷宮的行數和列數,接下來m行,每行包括n個字元,其中字元'.'表示該位置為空地,字元'*'表示該位置為障礙,輸入資料中只有這兩種字元,每組測試資料的最後一行為5個整數k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能轉的彎數,(x1, y1), (x2, y2)表示兩個位置,其中x1,x2對應列,y1, y2對應行。

output

每組測試資料對應為一行,若gloria能從乙個位置走到另外乙個位置,輸出「yes」,否則輸出「no」。

sample input

2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3

sample output

no yes

題解:可以用dfs搜尋所有情況判斷是否有滿足題目條件的。定義乙個結構體node,成員變數有x,y表示行列座標,dir表示方向,count表示轉彎次數。bool dfs(node node)就表示滿足的node節點能否走到終點。

從起點開始判斷,只需要四次迴圈,走上下左右四個方向,任何乙個方向dfs返回true就說明可以走到終點,否則不能。

每次dfs乙個節點時,需要先判斷是否是牆,是否越界,轉彎次數是否超標。最重要的是需要剪枝,如果dfs到某個node時,之前可能已經搜過該node了,就需要判斷是否需要剪枝,如果判斷出之前搜過該點,並且之前搜該店時最小的轉彎次數比本次搜該點的轉彎次數小(有點繞),那麼現在去搜這個點肯定肯定走不到終點,所以需要直接return false來剪枝,沒有這步剪枝應該會tle。

為了容易看明白些,**有些可以省略簡寫的地方沒有省略,比如搜4個方向可以for迴圈,這裡就直接貼了4遍**。

#include #include #include #define top 0

#define bottom 1

#define left 2

#define right 3

using namespace std;

int m,n; // 地圖行列數

int max; // 最多轉彎次數

char map[105][105]; // 存放地圖,從1開始

// 避免走回頭路,要滿足該點visited且轉彎次數更大

bool visited[105][105]; //每個點訪問記錄

int visitedcount[105][105]; // 記錄每個點訪問時的轉彎次數

struct node

}start,end; // 起始點和目標點

/** * 深度優先搜尋

*/bool dfs(node node) else

}if (x < 1 || y < 1 || x > m || y > n)

if (node.count > max)

if (x == end.x && y == end.y)

/** 該點可以走

*/visited[x][y] = true;

visitedcount[x][y] = node.count;

node temp;

// 走四個方向

// 上

temp.x = x - 1,temp.y = y,temp.dir = top;

temp.count = (node.dir == top ? node.count : node.count+1);

// 起點特判

if (node.x == start.x && node.y == start.y)

temp.count = 0;

if (dfs(temp) == true)

return true;

// 下

temp.x = x + 1,temp.y = y,temp.dir = bottom;

temp.count = (node.dir == bottom ? node.count : node.count+1);

if (node.x == start.x && node.y == start.y)

temp.count = 0;

if (dfs(temp) == true)

return true;

// 左

temp.x = x,temp.y = y - 1,temp.dir = left;

temp.count = (node.dir == left ? node.count : node.count+1);

if (node.x == start.x && node.y == start.y)

temp.count = 0;

if (dfs(temp) == true)

return true;

// 右

temp.x = x,temp.y = y + 1,temp.dir = right;

temp.count = (node.dir == right ? node.count : node.count+1);

if (node.x == start.x && node.y == start.y)

temp.count = 0;

if (dfs(temp) == true)

return true;

return false;

}int main() else

}return 0;

}

HDOJ 1728 逃離迷宮(DFS)

problem description 給定乙個m n m行,n列 的迷宮,迷宮中有兩個位置,gloria想從迷宮的乙個位置走到另外乙個位置,當然迷宮中有些地方是空地,gloria可以穿越,有些地方是障礙,她必須繞行,從迷宮的乙個位置,只能走到與它相鄰的4個位置中,當然在行走過程中,gloria不能...

Hdoj 1728 逃離迷宮

problem description 給定乙個m n m行,n列 的迷宮,迷宮中有兩個位置,gloria想從迷宮的乙個位置走到另外乙個位置,當然迷宮中有些地方是空地,gloria可以穿越,有些地方是障礙,她必須繞行,從迷宮的乙個位置,只能走到與它相鄰的4個位置中,當然在行走過程中,gloria不能...

HDU1728逃離迷宮(dfs 剪枝)

解題思路 一開始覺得是深搜模板題也沒多想,結果wa,發現輸入的出發點和終點都是先列再行 坑 改了下,又wa。起初的book陣列我用來存結點是否走過,原來這裡出bug了,題意是讓我們找結點是否能在k次轉彎內抵達。這裡存在著可能這個結點上次搜超過k次了,但是我們把他標記走過,等到下次經過這卻沒超過k次,...