奇怪的电梯(洛谷P1135)
前言&吐槽
同样可以拿dfs,这道题怎么就难那么多呢?
题目描述

算法设计
dfs的基本框架就是遍历一个结点的每一条路,所以我们的算法大概可以设计成这样
void dfsInEveryFloor()
{
if (当前楼层 == 目标楼层)
{
做一些操作...
retrun;
}
if (满足电梯向上走的条件)
{
dfsInEveryFloor();
}
if (满足电梯向下走的条件)
{
dfsInEveryFloor();
}
}
我们假设step是所求的最小次数,sum为某一条路需要的次数,那么可以知道:
- 在一个结点处,无论向上还是向下,sum都应该加1,但是sum本身不应该改变,因为那样sum得出来就不是一条路的次数了,而是多条路的总次数
- 如果达到了目标,就可以置step了
- 如果sum已经大于step,那么这个路就已经不是最小的了,直接return结束递归
根据上述发现,我们将代码完善一下:
void dfsInEveryFloor(int now, int sum)
{
if (now == targetFloor)
{
step = min(step, sum); //sum与step的最小值
return;
}
if (sum > step)
{
return;
}
if (now + floor[now] <= N)
{
dfsInEveryFloor(now + floor[now], sum + 1); //如果这里使用sum++,求的是两条路加起来的次数
}
if (now - floor[now] > 0)
{
dfsInEveryFloor(now - floor[now], sum + 1);
}
}
但是这并不能解这道题,因为如果楼层的按钮为0的话,会造成无限递归
解决方案是,看看这条路的此结点有没有经过。
我们使用
bool floorState[205]; //因为楼层最多200
来保存状态
那么代码可以更改为
void dfsInEveryFloor(int now, int sum)
{
if (now == targetFloor)
{
step = min(step, sum); // sum与step的最小值
return;
}
if (sum > step)
{
return;
}
floorState[now] = 1; //已经过
if (now + floor[now] <= N && !floorState[now + floor[now]]) //下一个结点没经过
{
dfsInEveryFloor(now + floor[now], sum + 1); //如果这里使用sum++,求的是两条路加起来的次数
}
if (now - floor[now] > 0 && !floorState[now - floor[now]])
{
dfsInEveryFloor(now - floor[now], sum + 1);
}
floorState[now] = 0; //接下来要回溯到上一个结点走另一条路,此时已经是不同的路了,因此需要重置状态
}
到此为止,算法已经设计完了。接下来就进行实现吧
代码实现
#include <iostream>
using namespace std;
bool floorState[205] = {0}; //记录楼层状态(这条有没有被搜索)
int floorStep[205] = {0};
int N, A, B;
int step = 0x7fffff;
void dfs(int now, int sum)
{
if (now == B)
{
step = min(step, sum);
}
//因为寻找的是最短路径
if (sum > step)
{
return;
}
floorState[now] = 1; //该层被搜索
if (now + floorStep[now] <= N && !floorState[now + floorStep[now]])
{
dfs(now + floorStep[now], sum + 1);
}
if (now - floorStep[now] > 0 && !floorState[now-floorStep[now]])
{
dfs(now - floorStep[now], sum + 1);
}
//实际上上面那两个已经把当前楼层的情况搜完了
//因此下面需要回溯到新的路径时,需要重置状态
floorState[now] = 0;
}
int main()
{
cin >> N >> A >> B;
for (int i = 1; i <= N; i++)
{
cin >> floorStep[i];
}
dfs(A, 0);
if (step != 0x7fffff)
{
cout << step;
}
else{
cout << -1;
}
}
我也是才刚刚学DFS,若有不准确还请指出

浙公网安备 33010602011771号