洛谷 P1135 搜索
https://www.luogu.org/problemnew/show/P1135
题目描述
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1≤i≤N)上有一个数字Ki(0≤Ki≤N)电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3,3,1,2,5代表了Ki(K1=3,K2=3,…),从1楼开始。在1楼,按“上”可以到4楼,按“下”是不起作用的,因为没有−2楼。那么,从A楼到B楼至少要按几次按钮呢?
输入输出格式
输入格式:
共二行。
第一行为3个用空格隔开的正整数,表示N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为N个用空格隔开的非负整数,表示Ki。
输出格式:
一行,即最少按键次数,若无法到达,则输出−1。
输入输出样例
输入样例#1: 复制
5 1 5 3 3 1 2 5
输出样例#1: 复制
3
思路:很容易看出来是搜索,不过肯定是要剪枝的,不然肯定会TLE的。我们用dp[i]表示到达第i层最少需要按的次数,初始化为INF(0x3f3f3f3f),dfs有两个参数,一个是cur,代表当前在第cur层,一个是cnt,代表当前按了cnt次,很明显,如果cnt>=dp[cur]就可以直接return了,没必要继续递归下去。做了这个剪枝,速度就会快很多。当cur=e时更新最优解,就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int dp[205];
int a[205];
int n,b,e;
void dfs(int cur,int cnt);
int main()
{
scanf("%d %d %d",&n,&b,&e);
memset(dp,INF,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs(b,0);
printf("%d\n",dp[e]==INF?-1:dp[e]);
return 0;
}
void dfs(int cur,int cnt)
{
if(cur==e)
{
dp[cur]=min(dp[cur],cnt);
return ;
}
if(cnt>=dp[cur])
return ;
dp[cur]=cnt;
if(cur-a[cur]>=1)
dfs(cur-a[cur],cnt+1);
if(cur+a[cur]<=n)
dfs(cur+a[cur],cnt+1);
}
另外一种思路: 上面那个思路是dfs,下面这个思路其实是bfs, 只不过没用一般的bfs的写法。 dp数组同上只不过初始化为-1, bfs的一个很明显的特点就是: 当你第一次到达某个点时所用的步数必定就是到达该点的最少步数, 因此只要第一次访问到结束的层数就可以直接跳出循环(或者说返回)了。 那么实现也很简单:找按0次按钮就能达到的位置(初始位置), 向上、 向下更新dp; 找按1次按钮就能到达的位置……直到访问到了终点位置或者没有必要bfs下去了。(即向上向下都已经访问过了)
#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int dp[205]; //dp[i]代表走到第i层的最少次数
int a[205]; //a[i]代表第i层电梯上的数字
int n,b,e;
int main()
{
memset(dp,-1,sizeof(dp));
scanf("%d %d %d",&n,&b,&e);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
dp[b]=0;
int flag=1;//标记是否有必要继续判断下去
int cnt=0; //标记当前按了几次电梯
while(dp[e]==-1&&flag)
{
flag=0;
for(int i=1;i<=n;i++)
{
if(dp[i]==cnt)//找到当前情况下的最优解
{
if(i+a[i]<=n&&dp[i+a[i]]==-1)//未被访问过且未越界
{
dp[i+a[i]]=cnt+1;
flag=1;
}
if(i-a[i]>=1&&dp[i-a[i]]==-1)
{
dp[i-a[i]]=cnt+1;
flag=1;
}
}
}
++cnt;
}
printf("%d\n",dp[e]);
return 0;
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 绕过卡巴进程保护的一些总结
- Loki | 数据过期自动删除策略设计
- 【短道速滑二】古老的基于亮度平均值的自动Gamma校正算法。
- Docker-Compose基础与实战,看这一篇就够了
- 干货-python与安全(一)入门简介
- 怎么在vue的style标签里面使用变量?
- 幼儿园EasyNVR能力层安防监控平台调用视频直播流报404错误解决方案
- C# WinForm捕获全局异常
- 新时代渗透思路!微服务下的信息收集Ⅱ
- 【STM32F407开发板用户手册】第31章 STM32F407的SPI总线基础知识和HAL库API
- 【工具使用】红队工具之Faction
- 【WebGL】一次drawcall中绘制多个不同纹理的图形
- BERT的PyTorch实现
- 从echarts-for-react源码中学习如何写单元测试
- 好用到飞起的12个jupyter lab插件