bfs判重与减枝的区别

来源:互联网 发布:ubuntu移动文件夹命令 编辑:程序博客网 时间:2024/04/30 06:22

提到bfs,很多人第一反应是往往要做”状态判重“ 和 ”减枝“。两者有何区别?

我的理解是:

”判重“是保证程序在有限时间内有正确输出,不出现死循环。简单理解就是,走过的路不再走,防止绕圈圈的情况出现。

而”减枝“是在保证程序有正确输出的基础上,将不必要的搜索枝条减去。

一个是保证正确性,一个是提高效率。

我以以下例子来说明:

China New Grad Test 2014 Round B

Problem D. Dragon Maze

Problem

You are the prince of Dragon Kingdom and your kingdom is in danger of running out of power. You must find power to save your kingdom and its people. An old legend states that power comes from a place known as Dragon Maze. Dragon Maze appears randomly out of nowhere without notice and suddenly disappears without warning. You know where Dragon Maze is now, so it is important you retrieve some power before it disappears.

Dragon Maze is a rectangular maze, an N x M grid of cells. The top left corner cell of the maze is (0,0) and the bottom right corner is (N-1,M-1). Each cell making up the maze can be either a dangerous place which you never escape after entering, or a safe place that contains a certain amount of power. The power in a safe cell is automatically gathered once you enter that cell, and can only be gathered once. Starting from a cell, you can walk up/down/left/right to adjacent cells with a single step.

Now you know where the entrance and exit cells are, that they are different, and that they are both safe cells. In order to get out of Dragon Maze before it disappears, you must walk from the entrance cell to the exit cell taking as few steps as possible. If there are multiple choices for the path you could take, you must choose the one on which you collect as much power as possible in order to save your kingdom.

Input

The first line of the input gives the number of test cases, T.T test cases follow.

Each test case starts with a line containing two integers N andM, which give the size of Dragon Maze as described above. The second line of each test case contains four integersenx, eny, exx,exy, describing the position of entrance cell (enx, eny) and exit cell (exx, exy). ThenN lines follow and each line has M numbers, separated by spaces, describing theN x M cells of Dragon Maze from top to bottom. Each number for a cell is either-1, which indicates a cell is dangerous, or a positive integer, which indicates a safe cell containing a certain amount of power.

Output

For each test case, output one line containing "Case #x: y", where x is the case number (starting from 1). If it's possible for you to walk from the entrance to the exit, y should be the maximum total amount of power you can collect by taking the fewest steps possible. If you cannot walk from the entrance to the exit, y should be the string "Mission Impossible." (quotes for clarity). Please note that the judge requires an exact match, so any other output like "mission impossible." or "Mission Impossible" (which is missing the trailing period) will be judged incorrect.

Limits

The amount of power contained in each cell will not exceed 10,000.
1 ≤ T ≤ 30.
0 ≤ enx, exx < N.
0 ≤ eny, exy < M.

Small dataset

1 ≤ N, M ≤ 10.

Large dataset

1 ≤ N, M ≤ 100.

Sample


Input
 
Output
 
22 30 2 1 02 -1 53 -1 64 40 2 3 2-1 1 1 21 1 1 12 -1 -1 11 1 1 1
Case #1: Mission Impossible.Case #2: 7


发现这是一个迷宫问题,想到用 bfs 来解决。

普通的迷宫只需要求从起点到终点的最短路径,而该题要求出最短路径里面的获得能源最多的那条路径。

这个要求会导致程序上做如下改动:

如果找到了x点通过step步到达的第一种情况,普通迷宫则不再考虑其他到达x点的任何情况。但本题还需要考虑 通过step步可以到达x点的情况,因为他们可能获得更多的power(step+1)的情况仍然不考虑。


普通迷宫的 伪代码:

q.push(entry);flag[entry] = true;while (!q.empty()) {    cur = q.front();    if (cur == exit) break; // 走到了迷宫出口。    q.pop();    for each neibour of cur {        if (!flag[neibour]) //只有当这个点还没有访问过时,才push到队列中。             {flag[neibour] = true;   //进入队列,就表明即将会被遍历,所以直接将那位flag置为true              q.push(neibour);}    }}

本题迷宫的伪代码:

max_power[MAX_NODE] = {0}; //到达各点能获取到的最大能量值q.push(entry);while (!q.empty()) {    cur = q.front();    if (cur == exit) {        if (第一次到达exit) 将最大能量值置为当前能量值,将step置为当前step;        else if (step==当前step) 更新最大能量值;        else break;    }    q.pop();    flag[cur] = true; //注意 置位这条语句,放在了当层遍历,而不是上面程序的下层push    for each neibour of cur {        if (!flag[neibour]) {    //注意!!! 这里是判重!!也就是说,step访问过,step+1就不能再访问了。            if (neibour.power > max_power[neibour]) {  //这里是减枝,只考虑到达那个点时的power值比之前大的情况。                max_power[neibour] = neibour.power;                q.push(neibour);            }        }    }}