搜狐2017秋招研发工程师笔试 —— 袋鼠过河(贪心、动态规划、转为图)
来源:互联网 发布:淘宝怎么看别人日销量 编辑:程序博客网 时间:2024/05/17 02:42
题目
测试链接
一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子,每隔一米就有一个,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳的更远。每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5,就代表袋鼠下一跳最多能够跳5米,如果为0,就会陷进去无法继续跳跃。河流一共N米宽,袋鼠初始位置就在第一个弹簧上面,要跳到最后一个弹簧之后就算过河了,给定每个弹簧的力量,求袋鼠最少需要多少跳能够到达对岸。如果无法到达输出-1 。
输入描述:
输入分两行,第一行是数组长度N (1 ≤ N ≤ 10000),第二行是每一项的值,用空格分隔。
输出描述:
输出最少的跳数,无法到达输出-1
示例1
输入
5
2 0 1 1 1输出
4
我觉得网站的测试用例不全面,你们可以用下面我单独给出的样例再测一下自己的贪心算法:
输入: 14 5 1 2 0 4 2 0 2 0 4 0 0 1 1输出: 5
思路
方法一 转换为图求最短路径
把线性模型转换为有向图,判断是否存在源点到终点的最小路径即可,时间复杂度O(VE)。
N个木桩,编号 0 — N-1;
每一个木桩后面都可能跟着一个可达点集合,据此构建该点与其所有子节点的连接关系;
用 Bellman-ford 算法对该图以0号木桩为源点寻最小路径即可。
注意:因为到达木桩 N-1 时还不算过河,需要添加一个辅助木桩N作为终点
方法二 动态规划
明天再写…
方法三 贪心策略
只需要维护一个可达区间,复杂度O(n^2)。
① 从当前落点a,根据在该点可跳的最远步长得到可达集S
②从S中找下一跳能到达最远处的点Si
③令a = Si,重复①②步直到可达集S包含岸点,或无法继续更新可达集
例子如下:
14个点,每个点的可跳数如图
上图符号▲为每次跳到的点,箭头指向的是它可达区间的右边界
代码
方法一 转换为图求最短路径
#include <iostream>#include <vector>#include <algorithm>#include <limits.h>using namespace std;int main() { int N; cin >> N; int *stone = new int[N + 1]; stone[N] = 0;// 辅助点,转换为图时需要该点作为终点,存在最小路径到该点则能过河 for (int i = 0; i < N; i++) cin >> stone[i]; // 构建邻接表, 时间复杂度O(V + E) vector<vector<int> > map; for (int curr_node = 0; curr_node < N + 1; curr_node++) { vector<int> node; for (int subNode = curr_node + 1; subNode <= curr_node + stone[curr_node] && subNode < N + 1; subNode++) { node.push_back(subNode); } map.push_back(node); } // 用 Bellman - ford 找起始点到辅助终点的最小路径,时间复杂度O(VE) vector<int> step(N + 1, INT_MAX); step[0] = 0; for (int i = 1; i < N + 1; i++) { for (int node = 0; node < N + 1; node++) { if (step[node] == INT_MAX) continue; for (int sub_i = 0; sub_i < map[node].size(); sub_i++) { int subNode = map[node][sub_i]; step[subNode] = min(step[subNode], step[node] + 1); } } } cout << (step[N] == INT_MAX ? -1 : step[N]) << endl; return 0;}
方法三 贪心策略
#include <iostream>#include <vector>#include <algorithm>#include <limits.h> using namespace std;int main() { // 初始化输入数据 int N = 0; cin >> N; vector<int> stone(N); for (int i = 0; i < N; i++) cin >> stone[i]; // 区间起点、区间右边界、新的区间起点、答案 int base, rightMost, new_base, res; // 到达每个点的跳数 vector<int> step(N); step[0] = 0; bool is_ok = false; for ( base = 0, rightMost = stone[0]; base < N; base = new_base) { // 更新可达区间 rightMost = new_base = base; for (int i = base + 1; i <= base + stone[base] && i < N; i++) { // 避免对之前已经能到达的点重复加步数 if(!step[i]) step[i] = step[base] + 1; if (stone[i] && rightMost < i + stone[i]) { new_base = i; rightMost = i + stone[i]; //已经能到河对岸,终止循环 if (rightMost >= N) { res = (i == N - 1 ?step[N - 1] + 1: step[new_base] + 1); is_ok = true; break; } } } // 过河 if (is_ok) break; // 可达区间为 0 ,没法再继续跳 if (base == new_base) break; } cout << (is_ok? res: -1)<< endl; return 0;}
阅读全文
0 0
- 搜狐2017秋招研发工程师笔试 —— 袋鼠过河(贪心、动态规划、转为图)
- 搜狐2017秋招研发工程师笔试题目
- 搜狐2018研发工程师秋招笔试题
- 搜狐笔试题目一袋鼠过河
- 搜狐 2017秋招研发
- 动态规划之袋鼠过河问题
- 马戏团(动态规划)---搜狐2016研发工程师编程题
- 阿里巴巴 2014校招 研发工程师 笔试
- 百度校招研发工程师笔试题
- 搜狐2017 WEB前端开发 秋招笔试编程题
- 利用贪心算法计算袋鼠过河问题
- 2015秋招阿里巴巴笔试题——系统工程师
- 2017 51信用卡秋招笔试题——JAVA研发
- 袋鼠过河
- 袋鼠过河
- 笔试题目——研发工程师笔试题
- 滴滴出行2017春招研发工程师笔试题-翻转单词顺序
- 滴滴出行2017春招研发工程师笔试题-套娃
- Sql语句 读取Excel
- 临时内核页表的建立过程
- 单点登录原理与简单实现
- struts2+velocity搭建
- keras搬砖系列-分类
- 搜狐2017秋招研发工程师笔试 —— 袋鼠过河(贪心、动态规划、转为图)
- 【3分钟带你学】接口
- Linux PAM 验证
- 【思路】商品新增
- Linux下github使用
- 页表及内存映射
- Add Two Numbers
- 使用npm install报错-4048 operation not permitted问题
- 【思路】商品修改