题目描述

深秋季节,天气渐凉,三叶由于最近期中考试太过忙碌,连续熬夜,不慎染上了感冒。泷听说后,非常担忧,于是决定出发去看三叶。已知泷和三叶处在一个矩形网格上,泷每次可以上下左右移动一格,但是他不能越过边界。要知道,泷虽然擅长体育,但是他的体力毕竟是有限的,已知泷的初始体力为6点,他每移动一格就要耗费一点体力,如果体力耗尽他就不能继续前进。幸运的是,三叶预想到了这一点,于是她提前请人帮忙在一些网格上放置了亲手做的便当。如果泷到达了放有便当的网格,那么他的体力值可以瞬间得到补充,恢复为6。值得注意的是,如果泷到达有便当的网格时体力已经为0,则他连吃饭的力气都没有了,就视为不可到达。如果他到达终点时体力为0,也视为不可到达。已知泷每走一格耗时为1,网格上的有些点上有不可逾越的建筑物,不能通过。

  • 数字 0:建筑物。(不允许通过)
  • 数字 1:空地,泷可以自由行走。
  • 数字 2:泷出发点, 也是一片空地。(行程起点)
  • 数字 3:三叶所在地。(行程终点)
  • 数字 4:便当所在地。

以标号为2的网格为起点,标号为3的网格为终点,问,泷能否见到三叶?如果能, 最短需要多长时间呢?

输入格式

第一行两个数字,网格的行数和列数,n,m。

第2至n+1行,描述整个网格。

输出格式

如果可到达,输出最短用时,否则输出-1。

样例输入

3 3
2 1 1
1 1 0
1 1 3

样例输出

4

数据范围

  • 对于 70 % 70\% 70%的数据 0 < n , m ≤ 20 0<n,m \le 20 0<n,m≤20;
  • 对于 30 % 30\% 30%的数据 0 < n , m ≤ 300 0<n,m \le 300 0<n,m≤300.

题目解答

好难的一道题似乎(没错我卡了三天o(╥﹏╥)o)最后还是一位ACM的大佬指点下才做出来的

      所以这个题目加入了能量值考虑,这就很麻烦了,我之前也考虑了很多递归的算法,但是结果不是超时就是答案错误。不妨列一下可能会有的问题:希望也可以帮助初学这个题目的玩家2333。

  • 问题一:到底是用BFS还是用DFS?
  • 解答:实践证明DFS只能通过 70 % 70\% 70% 的数据。 题目数据中有 70 % 70\% 70% 的数据地图规模是小于20格的,可以在规定时间内通过。但是一旦规模扩大了(达到300的边长的时候)就会超时!
  • 问题二:可否通过减分支的方法优化DFS ?
  • 解答:不可以,还是会超时!实践证明,当我们减去 超过 6 步以上仍然没有食物的路线,减去 在递归途中就超过已经找到可行方案的距离,规模扩大了(达到300的边长的时候)依然会超时
  • 问题三:可否结合递归与BFS一起查找?具体思路如下,利用BFS查找出发点周围 5 步以内的地图,(因为6步的时候一定人会没有吃的然后挂了)然后在以地图里面查找到的食物点作为起点,利用递归,在新的起点继续查找?
  • - 解答:不可以,首先,假设一个非常变态的情况,地图里面除了起点和终点全部是便当,那这个函数就会爆炸。其次,如果在查找的没有标记,这个函数就是一个死循环,起点 -> A便当 -> B便当 -> A便当 -> B便当 ……无穷无尽循环,更何况还有 C,D,E便当更多的循环。
  • 问题四:(接问题三)如果我标记了会怎么样?
  • 解答:首先,利用BFS查找出发点周围 5 步以内的地图,这个步骤相当于一个雷达,扫描周围的环境,扫描的结果是可能找到若干的便当,也可能啥都没找到。如果是后者那没事了搜索停止,如果是前者,我们要决定搜索方法,怎么搜索,这若干个便当,是全部作为起点,还是按照条件筛选出部分作为新的起点,然后再去查找。
  • 问题五:(接问题四)可否在最开始前以终点为中心,扫描周围环境,保存在一个数组里面,然后以起点为中心,步数为5扫描周围环境,比较所有的便当离终点的距离,选距离终点最近的便当到达,然后循环递归,直到终点?
  • 解答:不可以,实践证明,这种方法只能通过 70 % 70\% 70% 的数据。原因如下。假设下面这种图,空白的是空地,起点和终点是2,3,用黄色和橙色标出,蓝色的是食物,红色的是禁止去的区域。显然,唯一的方法是往上面绕远路,不能走下面的近路,但是按照问题里面所说的,以终点为雷达扫描周围距离,再以起点扫描周围步数5,会找到两个便当(这没错,一个在起点正北,另一个正南),然后判断这两个便当,显然是下面的便当距离终点近,递归进入第二层,以正南的便当作为起点,发现周围没有吃的了,就会报错认为无法到达。
  • 问题六:如何解决这种问题?
  • 解答:建立三维数组,我们假设这一片区域是一个有6层楼房的区域。(说白了就是变成原来的每个二维区域里面又有了高度。)开始的时候我们在起点的六楼,然后我们往周围查找,每移动一个,下一层高度,一旦有吃的立马恢复到六楼,一旦人到了一楼而且没有吃的人就挂了。这个是整体的思路。
  • 问题七:如何记录走的步数?
  • 解答:首先我们要初始化这个三维数组空间的所有元素为 INT_MAX ,然后起点的六楼我们单独修改值为 0。开始查找,【比如在水平面往北可以走,那就往北走,还是用队列的知识,但是往北走的楼层数要降低为5楼(能量消耗一个)坐标、楼层都要记录下来,用 push 函数推入队伍中。】大括号内容重复,向北向南向东向西搜索,可以就入队,然后再队伍里每次读取一个继续搜索。
  • 问题八:如何避免重复搜索,重复吃便当?
  • 解答:首先,我们走的步数肯定是远远小于 INT_MAX = 21474836470 的值的。即使是最大的地图。与其单独开一个数组什么的记录已经搜索的,不如我们就用三维数组的数字来判断是否搜索过。如果值是 INT_MAX = 21474836470 ,肯定没搜索过。
  • 问题九:可否定义一个 二维的bool数组 来记录下已经搜索的水平位置,然后在每次搜索之前, 用二维bool数组决定是否搜索该坐标,避免重复搜索,重复吃便当?
  • 解答:不可以!这样会导致补充便当后,部分位置的数据没有更新!!!例如,浅蓝色是我们当前队伍里面队首,我们的搜索顺序是先南,然后东,然后北,最后西,(灰色)搜索完南部的那个位置后,我们搜索东部,发现有吃的,好呀,但是此时浅蓝色位置、浅蓝色南部的位置都被搜索了,做好标记,不会再搜索了,所以 从浅蓝色往东那个分支就自然而然的终结了,为什么?因为你用的是bool数组来决定是否搜索该坐标,往东的那个分支最多搜索向南一次,然后终结,程序失败。
          那 从浅蓝色往西的那个分支呢,也会终结,无法到达位置 3。为什么,因为没能量啦。所以这就说明,不能用二维bool数组决定是否搜索该坐标。
  • 问题十:如何理解用三维数组的数字来判断是否搜索过?可以避免重复。
  • 解答:确实这是一个有一点抽象的问题,我们这样想。假设开始有一个毒气弹,放在起始的位置的六楼,然后这个毒气弹爆炸,开始向周围扩散,水平方向扩散一格,楼层数降低一,一旦毒气弹的气体扩散到了一楼,有没有遇上便当,那这个毒气自动失效,不再扩散。这就是这个问题的模型。此外,毒气每进入一个新的三维空间之前,都要判断之前有没有毒气已经进来过,进入新空间后,都要在里面写下花费的时间[或者说是距离]。
          那么我们描述某一处毒气的扩散情况需要什么参数呢?一个参数是扩散的时间(也就是从起点到该时刻毒气扩散的距离),另一个参数是当前的三维坐标。最初的时候三维坐标都被初始化 INT_MAX ,一旦被修改,一定就是之前已经有毒气到达,后来毒气在进入每一个三维空间前都要判断之前有没有进入过,如果之前进入过,那么现在这一段毒气进入完全没有必要,(为啥?之前已经有毒气进去了,之前的毒气花费的时间[或者说是距离]明显要少,所以没有必要再扩散进去,这就掉头看看周围)。
  • 问题十一:如何处理便当问题?
  • 我们知道,在使用BFS的时候要用到两个变量 nowplace,nextplace,后一个变量指示的位置基于前一个变量,也就是说后一个变量要遍历前一个变量北、东、南、西的、距离一个单位的位置,nowplace每次要读取队伍最前面的元素,然后把队伍最前面的元素弹出,所以处理便当问题有两个选择,一个选择是基于 nowplace,判断它【也是队queue最前面的元素】那里是不是有便当,另一个选择是基于 nextplace 判断。
          思考一下,你就会选择第二种。【理由】两个选择我们还是用毒气模型来解释,第一个选择就是,管他所在的位置有没有便当,先扔进队伍里面push进来,然后后面慢慢来处理,如果后来检测到有便当,我们就把位置升高到六楼,第二个选择就是,我在push进队伍里面之前,先看看有没有便当,有的话就直接扩散到六楼。显然第二个更好理解吧,不会调整位置升来升去的。就很头大,而且升高位置后改数据也很麻烦。【其实差别应该不大吧,效果是等效的应该,个人觉得】好处就是,选择第二种我们可以快速过滤数据,队伍里的东西,只要坐标是一楼,统统pass,为什么?之前已经通过食物有无检测了,还在一楼只能挂,没食物了,就算周围有食物,按照题目所说,体力为0 的时候不能吃东西。
  • 问题十二:搜索到终点后还会搜索吗?
  • 解答:是的,可能会。还是用毒气扩散模型,如果到了终点,并且是2楼以上,就会继续搜索周围的环境,继续扩散。但是,为了提高程序效率,你也可以就此终止,用一个 if 判断就可以实现终止,记得还有队列要清空哦~

上AC代码!!! 如果还是不好理解,你不妨把之前的二维的广度优先搜索转换为三维的广度优先搜索,代码就很好理解了,值得注意的是,一旦到了一楼就要终止!因为没能量了。代码我还是加一下注释,方便阅读

#include <iostream>
#include <string.h>
#include <limits.h>
#include <queue>
using namespace std;class node
{public:int x;int y;int height;                     // 与之前不同的是,多了一个height 表示楼层
};node departure, destination;
int m, n;
int testmap[310][310];
int stepmap[310][310][7];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int memsetmax;void bfs(node departure)
{stepmap[departure.x][departure.y][6] = 0;     // 起点六楼初始化0queue<node> bfsque;node nowplace, nextplace;bfsque.push(departure);while(!bfsque.empty()){nowplace = bfsque.front();bfsque.pop();if(nowplace.height == 1)   // 到一楼了,直接pass{continue;}for (int i = 0; i < 4; i++){nextplace.x = nowplace.x + dx[i];nextplace.y = nowplace.y + dy[i];nextplace.height = nowplace.height - 1;if (nextplace.x < 0 || nextplace.x >= n || nextplace.y < 0 || nextplace.y >= m || testmap[nextplace.x][nextplace.y] == 0){continue;             // 数组下标不合法,直接pass}if(testmap[nextplace.x][nextplace.y] == 4 )  // 处理有便当的 nextplace {if(stepmap[nextplace.x][nextplace.y][6] == memsetmax){nextplace.height = 6;             // 调整到六楼stepmap[nextplace.x][nextplace.y][6] = stepmap[nowplace.x][nowplace.y][nowplace.height] + 1;bfsque.push(nextplace);               // 入队!}}else if (stepmap[nextplace.x][nextplace.y][nextplace.height] == memsetmax){stepmap[nextplace.x][nextplace.y][nextplace.height] = stepmap[nowplace.x][nowplace.y][nowplace.height] + 1;bfsque.push(nextplace);                // 同bfs常见操作}}}
}int main()
{memset(stepmap, 127, sizeof(stepmap));     // 值得一提的是 这个操作不是把所有值设为127memsetmax = stepmap[0][0][0];             // 而是一个很大的值,接近 INT_MAXcin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> testmap[i][j];switch (testmap[i][j]){case 2:departure.x = i;departure.y = j;departure.height = 6;break;case 3:destination.x = i;destination.y = j;break;default:break;}}}int result = memsetmax;bfs(departure);for (int i = 1; i <= 6; i++){result = min(stepmap[destination.x][destination.y][i], result);}if (result == memsetmax)cout << "-1";elsecout << result;system("pause");return 0;
}

小结 三维广度优先搜索

三维广度优先搜索可以解决带有能量值的途径问题,本质是BFS搜索,模型是毒气扩散,按照楼层递减,实现途径是在class类定义的时候多定义一个变量即可,然后再后续的时候,考虑到楼层 height 的变化。其余的同之前的BFS搜索即可。若有问题,可以参考上面的样例问题,是我在写程序的时候遇到的,经历了三天的试错后总结的问题,新手也很可能有类似的问题,可以攻参考。 最后附上自己写错的代码,纪念一下下。

错误的尝试

尝试一 DFS

【错误原因】超时,不适合大地图。

#include <iostream>
#include <limits.h>
#include <string.h>
using namespace std;class node
{public:int x;int y;
};node departure,destionation;
int n, m;
int testmap[310][310];
bool book[310][310];
bool IfFind = false;
int result = INT_MAX;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};void dfs(int nx,int ny,int energy,int distance)
{if (energy <= 1 && testmap[nx][ny] != 4){return;}if (distance >= result){return;}if (nx == destionation.x && ny == destionation.y){IfFind = true;if (distance < result){result = distance;}return;}if (testmap[nx][ny] == 4){energy = 6;}int ntx, nty;for (int i = 0; i < 4; i++){ntx = nx + dx[i];nty = ny + dy[i];if (ntx >= n || ntx < 0 || nty >= m || nty < 0 || testmap[ntx][nty] == 0){continue;}if (book[ntx][nty] == false){book[ntx][nty] = true;dfs(ntx, nty, energy - 1, distance + 1);book[ntx][nty] = false;}}
}int main()
{memset(book, false, sizeof(book));cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> testmap[i][j];switch (testmap[i][j]){case 2:departure.x = i;departure.y = j;break;case 3:destionation.x = i;destionation.y = j;default:break;}}}dfs(departure.x, departure.y, 6, 0);if (IfFind == false){cout << "-1";}elsecout << result;system("pause");return 0;
}

尝试二 BFS

【错误原因】沉下心来想这是最接近成功的一次,几乎就啊哟呼之欲出了三维数组,错误原因在于用 bool 数组判断是否到过某些位置。具体分析见上文。

#include <iostream>
#include <string.h>
#include <queue>
using namespace std;class node
{public:int x;int y;int energy;
};node departure,destionation;
int n, m;
int testmap[310][310];
int step[310][310];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
bool ifArrive[310][310];bool bfs_CheckNextstep(node checkobject)
{if (checkobject.x < 0 || checkobject.x >= n)return false;if (checkobject.y < 0 || checkobject.y >= m)return false;if (testmap[checkobject.x][checkobject.y] == 0)return false;if (ifArrive[checkobject.x][checkobject.y] == true)return false;if (checkobject.energy == 0)return false;else return true;// if (checkobject.x >= 0 && checkobject.x < n && checkobject.y >= 0 && checkobject.y < m && checkobject.energy > 0 && ifArrive[checkobject.x][checkobject.y] == false)//     return true;// else//     return false;
}// 广度优先搜索,传入的时候传入一个节点node!
void bfs_Main(node departure)
{memset(step, 0, sizeof(step));memset(ifArrive, false, sizeof(ifArrive));// 首先定义一个队列!queue<node> bfsque;bfsque.push(departure);ifArrive[departure.x][departure.y] = true;node currentplace, nextplace;while (!bfsque.empty()){currentplace = bfsque.front();bfsque.pop(); // 把最前面的元素弹出去!if (testmap[currentplace.x][currentplace.y] == 4){currentplace.energy = 6;}        for (int i = 0; i < 4; i++){nextplace.x = currentplace.x + dx[i];nextplace.y = currentplace.y + dy[i];nextplace.energy = currentplace.energy - 1;if (bfs_CheckNextstep(nextplace) == true){step[nextplace.x][nextplace.y] = step[currentplace.x][currentplace.y] + 1;ifArrive[nextplace.x][nextplace.y] = true;bfsque.push(nextplace);}}}
}int main()
{cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> testmap[i][j];switch (testmap[i][j]){case 2:departure.x = i;departure.y = j;departure.energy = 6;ifArrive[departure.x][departure.y] = true;break;case 3:destionation.x = i;destionation.y = j;default:break;}}}bfs_Main(departure);cout << endl;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cout << step[i][j] << "\t";}cout << endl;}if (ifArrive[destionation.x][destionation.y] == false)cout << "-1" << endl;else cout << step[destionation.x][destionation.y];system("pause");return 0;
}

尝试三 BFS+递归

【错误原因】没搞清楚递归的起点如何选择

#include <iostream>
#include <queue>
#include <string.h>
#include <limits.h>
using namespace std;class node
{public:int x;int y;
};class foodnode
{public:int x;int y;
};foodnode foodplace[100000];
node departure, destionation;
int m, n;
int testmap[310][310];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int foodnum = 0;// 只找六步以内!
void find_Surrounding(node departure)
{bool ifChecked[310][310];int step[310][310];memset(ifChecked, false, sizeof(ifChecked));memset(step, 0, sizeof(step));queue<node> bfsque;ifChecked[departure.x][departure.y] = true;node nowplace, nextplace;bfsque.push(departure);while (!bfsque.empty()){nowplace = bfsque.front();bfsque.pop(); // 把最前面的元素弹出去!for (int i = 0; i < 4; i++){nextplace.x = nowplace.x + dx[i];nextplace.y = nowplace.y + dy[i];if (nextplace.x >= n || nextplace.x < 0 || nextplace.y >= m || nextplace.y < 0 || testmap[nextplace.x][nextplace.y] == 0){continue;}if (ifChecked[nextplace.x][nextplace.y] == false && step[nowplace.x][nowplace.y] < 5){step[nextplace.x][nextplace.y] = step[nowplace.x][nowplace.y] + 1;// cout << "nextplace.x:  " << nextplace.x << endl;// cout << "nextplace.y:  " << nextplace.y << endl;// cout << "step[nextplace.x][nextplace.y]:  " << step[nextplace.x][nextplace.y] << endl;ifChecked[nextplace.x][nextplace.y] = true;bfsque.push(nextplace);}}}// for (int i = 0; i < m; i++)// {//     for (int j = 0; j < n; j++)//     {//         cout << step[i][j] << "\t";//     }//     cout << endl;// }
}int main()
{cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> testmap[i][j];switch (testmap[i][j]){case 2:departure.x = i;departure.y = j;break;case 3:destionation.x = i;destionation.y = j;break;case 4:foodplace[foodnum].x = i;foodplace[foodnum].y = j;foodnum++;break;default:break;}}}find_Surrounding(departure);system("pause");return 0;
}

尝试四 BFS+递归

【错误原因】同上

#include <iostream>
#include <cstring>
#include <queue>
#include <limits.h>
using namespace std;class node
{public:int x;int y;
};class foodnode
{public:int x;int y;int step;
};node departure, destination;
int testmap[310][310];
int step_for_findSurronding[310][310];
int step_for_destination[310][310];
bool book_for_departure_surrending[310][310];
bool foodmap[310][310];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int m, n;
int result = INT_MAX;
bool If_Meet = false;bool common_check(node object)
{if (object.x < 0 || object.x >= n)return false;if (object.y < 0 || object.y >= m)return false;if (testmap[object.x][object.y] == 0)return false;else return true;
}void destination_surronding(node destination)
{bool book_for_destination_surronding[310][310];memset(book_for_destination_surronding, false, sizeof(book_for_destination_surronding));memset(step_for_destination, 0, sizeof(step_for_destination));queue<node> bfsque;node nowplace, nextplace;bfsque.push(destination);book_for_destination_surronding[destination.x][destination.y] = true;while(!bfsque.empty()){nowplace = bfsque.front();bfsque.pop();for (int i = 0; i < 4; i++){nextplace.x = nowplace.x + dx[i];nextplace.y = nowplace.y + dy[i];if (common_check(nextplace) == true && book_for_destination_surronding[nextplace.x][nextplace.y] == false){step_for_destination[nextplace.x][nextplace.y] = step_for_destination[nowplace.x][nowplace.y] + 1;book_for_destination_surronding[nextplace.x][nextplace.y] = true;bfsque.push(nextplace);}}}} void print_departure_surronding()
{for (int i = 0; i < m; i++){for (int j = 0; j < n; j++){cout << step_for_findSurronding[i][j] << "\t";}cout << endl;}
}// 下面这个函数涉及到递归void departure_surrending(node departure, int distance)
{memset(book_for_departure_surrending, false, sizeof(book_for_departure_surrending));memset(step_for_findSurronding,0,sizeof(step_for_findSurronding));queue<node> bfsque1;queue<foodnode> foodtemp;node nowplace, nextplace;foodnode temp;  // 用于转换,以便于推入食物的队伍bfsque1.push(departure);book_for_departure_surrending[departure.x][departure.y] = true;while(!bfsque1.empty()){nowplace = bfsque1.front();bfsque1.pop();if(nowplace.x == destination.x && nowplace.y == destination.y){// 检测到终点If_Meet = true;distance = distance + step_for_findSurronding[nowplace.x][nowplace.y];if (distance < result){result = distance;}while(!bfsque1.empty())     bfsque1.pop();    return;}if (testmap[nowplace.x][nowplace.y] == 4 && foodmap[nowplace.x][nowplace.y] == false){temp.x = nowplace.x;temp.y = nowplace.y;temp.step = step_for_findSurronding[nowplace.x][nowplace.y];foodtemp.push(temp);}for (int i = 0; i < 4; i++){nextplace.x = nowplace.x + dx[i];nextplace.y = nowplace.y + dy[i];if (common_check(nextplace) == true && book_for_departure_surrending[nextplace.x][nextplace.y] == false && step_for_findSurronding[nowplace.x][nowplace.y] <= 4){step_for_findSurronding[nextplace.x][nextplace.y] = step_for_findSurronding[nowplace.x][nowplace.y] + 1;book_for_departure_surrending[nextplace.x][nextplace.y] = true;bfsque1.push(nextplace);}}}cout << "!--------------------------!" << endl;print_departure_surronding();if(!foodtemp.empty()){int steptemp;foodnode first, last;last = foodtemp.back();first = foodtemp.front();// 下面开始递归!// cout << foodtemp.size() << endl;while ((first.step) < (last.step)){foodtemp.pop();first = foodtemp.front();}while (!foodtemp.empty()){departure.x = foodtemp.front().x;departure.y = foodtemp.front().y;steptemp = foodtemp.front().step;cout << "departure.x: " << departure.x << "   departure.y:   " << departure.y << endl;foodtemp.pop();foodmap[departure.x][departure.y] = true;departure_surrending(departure, distance + steptemp);}}}int main()
{memset(foodmap, false, sizeof(foodmap));cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> testmap[i][j];switch (testmap[i][j]){case 2:departure.x = i;departure.y = j;break;case 3:destination.x = i;destination.y = j;default:break;}}}destination_surronding(destination);departure_surrending(departure, 0);if (If_Meet == true)cout << result;elsecout << "-1";// print_destination_surronding();system("pause");return 0;
}

尝试五 BFS+递归

【错误原因】同上

#include <iostream>
#include <cstring>
#include <queue>
#include <limits.h>
using namespace std;class node
{public:int x;int y;
};class foodnode
{public:int x;int y;int step;long int walkstep;
};node departure, destination;
int testmap[310][310];
int step_for_findSurronding[310][310];
int step_for_destination[310][310];
bool book_for_departure_surrending[310][310];
bool foodmap[310][310];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int m, n;
long int result = 10000000;
bool If_Meet = false;bool common_check(node object)
{if (object.x < 0 || object.x >= n)return false;if (object.y < 0 || object.y >= m)return false;if (testmap[object.x][object.y] == 0)return false;else return true;
}void destination_surronding(node destination)
{bool book_for_destination_surronding[310][310];memset(book_for_destination_surronding, false, sizeof(book_for_destination_surronding));memset(step_for_destination, 0, sizeof(step_for_destination));queue<node> bfsque;node nowplace, nextplace;bfsque.push(destination);book_for_destination_surronding[destination.x][destination.y] = true;while(!bfsque.empty()){nowplace = bfsque.front();bfsque.pop();for (int i = 0; i < 4; i++){nextplace.x = nowplace.x + dx[i];nextplace.y = nowplace.y + dy[i];if (common_check(nextplace) == true && book_for_destination_surronding[nextplace.x][nextplace.y] == false){step_for_destination[nextplace.x][nextplace.y] = step_for_destination[nowplace.x][nowplace.y] + 1;book_for_destination_surronding[nextplace.x][nextplace.y] = true;bfsque.push(nextplace);}}}} void print_destination_surronding()
{for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cout << step_for_destination[i][j] << "\t";}cout << endl;}
}void print_departure_surronding()
{for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cout << step_for_findSurronding[i][j] << "\t";}cout << endl;}
}// 下面这个函数涉及到递归void departure_surrending(node departure, long int distance)
{memset(book_for_departure_surrending, false, sizeof(book_for_departure_surrending));memset(step_for_findSurronding,0,sizeof(step_for_findSurronding));queue<node> bfsque1;foodnode foodplace[50];int foodnum = 0;node nowplace, nextplace;bfsque1.push(departure);book_for_departure_surrending[departure.x][departure.y] = true;while(!bfsque1.empty()){nowplace = bfsque1.front();bfsque1.pop();if(nowplace.x == destination.x && nowplace.y == destination.y){// 检测到终点If_Meet = true;distance = distance + step_for_findSurronding[nowplace.x][nowplace.y];cout << "possible : " << distance << endl;if (distance < result){result = distance;}while(!bfsque1.empty()){bfsque1.pop();    }     return;}if (testmap[nowplace.x][nowplace.y] == 4 && foodmap[nowplace.x][nowplace.y] == false){foodplace[foodnum].x = nowplace.x;foodplace[foodnum].y = nowplace.y;foodplace[foodnum].step = step_for_destination[nowplace.x][nowplace.y];foodplace[foodnum].walkstep = step_for_findSurronding[nowplace.x][nowplace.y];foodnum++;}for (int i = 0; i < 4; i++){nextplace.x = nowplace.x + dx[i];nextplace.y = nowplace.y + dy[i];if (common_check(nextplace) == true && book_for_departure_surrending[nextplace.x][nextplace.y] == false && step_for_findSurronding[nowplace.x][nowplace.y] <= 4){step_for_findSurronding[nextplace.x][nextplace.y] = step_for_findSurronding[nowplace.x][nowplace.y] + 1;book_for_departure_surrending[nextplace.x][nextplace.y] = true;bfsque1.push(nextplace);}}}print_departure_surronding();cout << "!! foodnum  " << foodnum << endl;int mindistance = foodplace[0].step;for (int i = 0; i < foodnum; i++){cout << "possible step : " << (foodplace[i].step) << endl;if ((foodplace[i].step) < mindistance){mindistance = foodplace[i].step;}}for (int j = 0; j < foodnum; j++){if((foodplace[j].step) == mindistance){departure.x = foodplace[j].x;departure.y = foodplace[j].y;cout << "departure.x: " << departure.x << "   departure.y:   " << departure.y << endl;foodmap[departure.x][departure.y] = true;departure_surrending(departure, distance + foodplace[j].walkstep);}}
}int main()
{memset(foodmap, false, sizeof(foodmap));cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> testmap[i][j];switch (testmap[i][j]){case 2:departure.x = i;departure.y = j;break;case 3:destination.x = i;destination.y = j;default:break;}}}destination_surronding(destination);cout << "打印终点附近坐标" << endl;print_destination_surronding();cout << "打印终点附近坐标结束" << endl;departure_surrending(departure, 0);if (If_Meet == true)cout << result;elsecout << "-1";system("pause");return 0;
}

(新版)SJTU-OJ-1032. 泷的旅途相关推荐

  1. 【算法学习笔记】65. 双向扫描 SJTU OJ 1382 畅畅的牙签盒

    http://acm.sjtu.edu.cn/OnlineJudge/problem/1382 注意到 排序之后 i从前向后扫描时,cur恰好是从后向前的,所以即使是双重循环,也是O(n)的算法. # ...

  2. 【算法学习笔记】43.动态规划 逆向思维 SJTU OJ 1012 增长率问题

    1012. 增长率问题 Description 有一个数列,它是由自然数组成的,并且严格单调上升.最小的数不小于S,最大的不超过T.现在知道这个数列有一个性质:后一个数相对于前一个数的增长率总是百分比 ...

  3. 【算法学习笔记】57. 前缀树 字典序优化技巧 STL学习 SJTU OJ 1366 前缀匹配

    Description 给出一个总字符个数大小不超过1,000,000的字典(这个字典的单词顺序不为字典序)和不超过1000个长度不超过1000的前缀,输出字典中匹配该前缀,字典序为K_i的单词在字典 ...

  4. 【算法学习笔记】35.高精度 竖式乘法 SJTU OJ 1274

    Description 输入a,b 输出a*b的竖式乘法,格式见样例. Sample Input1 11 9 Sample Output1 119 -- 99 Sample Input2 10 10 ...

  5. 【算法学习笔记】83.排序辅助 动态规划 SJTU OJ 1282 修路

    此题倒是能用贪心骗点分... 其实对于每一个位置 , 我们知道最后的改善结果一定是原数列中的数 . (因为要尽量减少消耗, 可以考虑减小至和相邻的相同) 有了这个结论之后, 我们就考虑用dp来做这件事 ...

  6. SJTU OJ 3046 足球 题解

    2019独角兽企业重金招聘Python工程师标准>>> 3046. 足球 Description 众所周知,一只足球队由11球员组成,其中有一名守门员和一名队长. 现在,有22人组成 ...

  7. 【算法学习笔记】85.破环为链 序列DP 松弛+代价 SJTU OJ 1073 能量项链

    和石子合并很像, 为了对环状进行处理, 我们可以把输入数据复制一份接连在后边. 这样在最后的结果枚举起点找最大即可. 注意这里代价的计算, 因为我们的data[i]只记录了珠子的头 , 珠子的尾部即是 ...

  8. 【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人

    Description 小M有很多个机器人,他们要么一直说真话,要么一直说假话. 然后每个人都说: (1). 不到N个人比我工作得多 (2). 至少M个人的工资比我高. 保证没有两个人的工作一样重,也 ...

  9. 【算法学习笔记】28.枚举法 解题报告 SJTU OJ 1255 1256 魔戒

    1256. 你的魔戒?不,是你的魔戒.加强版 Description 在前往末日火山的途中,佛罗多与他的霍比特人同胞不幸被半兽人抓住了.半兽人要对每个霍比特人进行询问,以找出哪个霍比特人携带了至尊魔戒 ...

最新文章

  1. JavaScript数据运算
  2. 通过Iframe在A网站页面内嵌入空白页面的方式,跨域获取B网站的数据返回给A网站!...
  3. tomcat日志格式中的含义
  4. why configuration from BSP application is loaded
  5. 暑期训练日志----2018.8.16
  6. python编程(深拷贝和浅拷贝)
  7. php扩展模块作用及中文注释
  8. imagenet classification with deep convolutional neural networks
  9. jQuery Mobile中头部栏header的data-*选项
  10. FMEA软件七步法(FMEAHunter)
  11. 阿里云EMAS 移动推送发布uni-app插件
  12. Exposure X8 ps人像图片调色滤镜插件
  13. 如何用计算机函数来求加权总分,Excel计算加权总分,函数公式还是超级表厉害,一起看看!-excel乘法函数...
  14. Python之字体反爬详细操作
  15. git lfs linux,Git LFS 操作指南
  16. 中兴F450电信光猫改桥接模式
  17. linux 远程启动WebLogic
  18. Maven的一个基础pom.xml文件结构
  19. 如何批量将 Word 文档转为 ePub 格式
  20. 【ICPC模板】多元一次不定方程(丢番图方程)求解

热门文章

  1. 桨力传感器 赛艇控制器
  2. win10安装EOP/op 解决 文件哈希值
  3. pc 安装玩centos 开机卡 switching_IT30: 统一标准新PC安装套路!
  4. Servlet与Jsp的区别
  5. CNET盘点2012年IT人物:进退得意还是没落迷茫
  6. Visio另存为无白色边框的pdf矢量图
  7. ESP32进行UDP广播的问题
  8. 无线监控出观服务器异常,手机连监控连接服务器异常什么原因
  9. 【笔记】ES6 数组的扩展
  10. java jsch下载文件,JSch使用sftp协议实现服务器文件上传下载操作