跳房子(弱化版)
题目描述
跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一。
跳房子的游戏规则如下:
在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一条直线上。每个格子内有一个数字(整数),表示到达这个 格子能得到的分数。玩家第一次从起点开始向右跳,跳到起点右侧的一个格子内。第二次再从当前位置继续向右跳,依此类推。规则规定:
玩家每次都必须跳到当前位置右侧的一个格子内。玩家可以在任意时刻结束游戏,获得的分数为曾经到达过的格子中的数字之和。
现在小 R 研发了一款弹跳机器人来参加这个游戏。但是这个机器人有一个非常严重的缺陷,它每次向右弹跳的距离只能为固定的 d。小 R 希望改进他的机器人,如果他花 g 个金币改进他的机器人,那么他的机器人灵活性就能增加 g,但是需要注意的是,每 次弹跳的距离至少为 11。具体而言,当 g<dg<d 时,他的机器人每次可以选择向右弹跳的距离为 d−g,d−g+1,d−g+2,…,d+g−1,d+gd−g,d−g+1,d−g+2,…,d+g−1,d+g;否则当 g≥dg≥d 时,他的机器人每次可以选择向右弹跳的距离为 1,2,3,…,d+g−1,d+g1,2,3,…,d+g−1,d+g。
现在小 R 希望获得至少 k 分,请问他至少要花多少金币来改造他的机器人。
输入格式
第一行三个正整数 n,d,k 分别表示格子的数目,改进前机器人弹跳的固定距离,以及希望至少获得的分数。相邻两个数 之间用一个空格隔开。
接下来 n 行,每行两个整数 xi,si 分别表示起点到第 i 个格子的距离以及第 i个格子的分数。两个数之间用一个空格隔开。保证 xi 按递增顺序输入。
输出格式
共一行,一个整数,表示至少要花多少金币来改造他的机器人。若无论如何他都无法获得至少 k 分,输出 −1。
输入格式
第一行三个正整数 n,d,k 分别表示格子的数目,改进前机器人弹跳的固定距离,以及希望至少获得的分数。相邻两个数 之间用一个空格隔开。
接下来 n 行,每行两个整数 xi,si 分别表示起点到第 i个格子的距离以及第 i个格子的分数。两个数之间用一个空格隔开。保证 xi 按递增顺序输入。
输出格式
共一行,一个整数,表示至少要花多少金币来改造他的机器人。若无论如何他都无法获得至少 k 分,输出 −1 。
输入输出样例
输入 #1复制
7 4 10 2 6 5 -3 10 3 11 -3 13 1 17 6 20 2
输出 #1复制
2
输入 #2复制
7 4 20 2 6 5 -3 10 3 11 -3 13 1 17 6 20 2
输出 #2复制
-1
说明/提示
样例 1 说明
花费 22 个金币改进后,小 R 的机器人依次选择的向右弹跳的距离分别为 2,3,5,3,4,32,3,5,3,4,3,先后到达的位置分别为 2,5,10,13,17,202,5,10,13,17,20,对应 1,2,3,5,6,71,2,3,5,6,7 这 66 个格子。这些格子中的数字之和 1515 即为小 R 获得的分数。
样例 2 说明
由于样例中 77 个格子组合的最大可能数字之和只有 1818,所以无论如何都无法获得 2020 分。
数据规模与约定
对于全部的数据满足 1≤n≤5001≤n≤500,1≤d≤2×1031≤d≤2×103,1≤xi,k≤1091≤xi,k≤109,∣si∣<105∣si∣<105。
---------------------------------------------------------------------------------------------------------------------------------
分析与解答:
A-G分别表示1号到7号格子,红色文字表示该格子对应的分值。
初始状态,当d = 4时,无法由起点跳到其它点,此时需要花费2金币改造,改造后机器人的移动范围变为[2,6],此时:
1. 机器人跳到A点,得6分,总分6分
2. 机器人跳到B点,得-3分,总分3分
3. 机器人跳到C点,得3分,总分6分
4. 机器人跳到E点,得1分,总分7分
5. 机器人跳到F点,得6分,总分13分
所以,当花费2金币进行改造时,得分不低于10分。
解答1:
算法思想(二分搜索+动态规划)
假设已求得了最优解,即花费g
个金币进行改造后,得分不低于k
。如果在此状态下再花费若干金币,那么得分一定不低于k
。因此花费的金币数和得分之间满足单调性质,是一个单调递增关系(不一定是严格单调递增),可以使用二分求解在花费不同金币进行改造时得分是否满足条件。
要求花费g
个金币进行改造后的最高得分,可以使用动态规划的思想:
状态表示: f[i]表示在花费g个金币进行改造后,跳过前i个格子得到的最高得分
状态转移:f[i] = max{f[j] + w[i]},其中max(1,d−g)≤dist[i]−dist[j]≤d+g
注:w[i]为i个格子的得分
时间复杂度 O(n×d×logxn) ,需要对DP进行剪枝。
#include<iostream>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int n,d,k;
int a[500010][2];
ll f[500010],sum=0;
bool check(int g) {cout<<"g="<<g<<' '<<endl;int l=max(1,d-g),r=d+g;cout<<"%%%"<<l<<' '<<r<<endl;memset(f,-127,sizeof f);f[0]=0;for(int i=1; i<=n; i++) {//每个格子int td;for(int j=0; j<i; j++) {//当前格子的前面格子,从小到大去寻找td=a[i][0]-a[j][0];cout<<"格子***"<<j<<" ,格子举例"<<td<<endl;if(td>=l&&td<=r) {// f[i]积分,当前i格子的分数f[i]=max(f[i],f[j]+a[i][1]);}if(f[i]>=k) return true;if(td<l) break;}cout<<i<<' '<<f[i]<<endl;}return false;
}int main() {scanf("%d %d %d",&n,&d,&k);for(int i=1; i<=n; i++) {scanf("%d %d",&a[i][0],&a[i][1]);if(a[i][1]>0) {cout << "a[" << i << "][1]" << endl;sum += a[i][1];cout << "sum = " << sum << endl;}}if(sum<k) {//所有的正分加起来都不够希望获得的分数printf("-1");return 0;}//二分int l=0,r=max(0,a[n][0]-d);cout << "a[" << n-1 << "][0]=" << a[n][0] << endl;cout << "d = " << d << endl;while(l<r) {cout<<'*'<<l<<' '<<r<<endl;int mid=(l+r)/2;if(check(mid)) r=mid;else l=mid+1;}printf("%lld",l);return 0;
}
解答2:基本思想
要解决这个问题,我们需要动态规划(Dynamic Programming,DP)的思想。我们要确定最少需要花费多少金币来改造机器人,使其能够获得至少 k
分。以下是详细的步骤和思路:
-
输入处理:
- 读取
n
,d
,k
。 - 读取每个格子的位置和分数。
- 读取
-
确定DP状态:
dp[i][j]
表示花费j
个金币时,到达第i
个格子能获得的最大分数。
-
状态转移:
- 对于每个格子
i
和每个花费j
,我们需要尝试所有可能的跳跃距离,并更新dp[i][j]
。 - 跳跃距离的范围根据
g
和d
的关系分为两种情况:- 当
g < d
时,跳跃距离范围是[d-g, d+g]
。 - 当
g >= d
时,跳跃距离范围是[1, d+g]
。
- 当
- 对于每个格子
-
初始化:
- 起点位置特殊处理,
dp[j]
初始化为 0(起点没有分数,但是可以作为跳跃的出发点)。
- 起点位置特殊处理,
-
结果计算:
- 遍历所有格子和所有花费,计算能得到的最大分数。
- 最终找到最小的花费
j
使得在某个格子上的分数大于等于k
。
-
边界情况处理:
- 如果无法获得至少
k
分,返回-1
。
- 如果无法获得至少
以下是实现该算法的C++代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>using namespace std;struct Grid {int position;int score;
};int main() {int n, d, k;cin >> n >> d >> k;vector<Grid> grids(n);for (int i = 0; i < n; ++i) {cin >> grids[i].position >> grids[i].score;}// 由于位置是按递增顺序输入的,我们可以直接使用下标来访问格子vector<vector<int>> dp(n + 1, vector<int>(n + 1, -1)); // n+1 个格子, 最多花费 n 个金币(松弛上界)dp = 0; // 在起点,不花费金币,得分为 0for (int g = 0; g <= n; ++g) { // 金币花费从 0 到 nfor (int i = 0; i < n; ++i) { // 遍历每一个格子if (dp[i][g] == -1) continue; // 如果当前状态不可达,跳过int minJump = max(1, d - g);int maxJump = d + g;for (int jump = minJump; jump <= maxJump; ++jump) {// 查找下一个可达的格子for (int next = i + 1; next <= n; ++next) {if (grids[next - 1].position - grids[i].position > jump) break;if (grids[next - 1].position - grids[i].position == jump) {dp[next][g] = max(dp[next][g], dp[i][g] + grids[next - 1].score);}}}}}int minCoins = INT_MAX;for (int g = 0; g <= n; ++g) {for (int i = 0; i <= n; ++i) {if (dp[i][g] >= k) {minCoins = min(minCoins, g);}}}if (minCoins == INT_MAX) {cout << -1 << endl;} else {cout << minCoins << endl;}return 0;
}
解释
- 初始化:
dp = 0
,其他均为-1
,因为初始时其他状态都是不可达的。 - 状态转移:通过遍历每一个格子和每一种花费,尝试所有可能的跳跃距离,更新
dp
数组。 - 结果计算:找到最小的花费
g
使得在某个格子上的分数大于等于k
。
该算法的时间复杂度为 O(n3)
,在合理的数据范围内是可以接受的。
---------------------------------------------------------------------------------------------------------------------------------
解答3:
为了解决这个问题,我们需要考虑机器人在不同金币花费下的弹跳能力,并计算出在每种情况下能够获得的最大分数。我们的目标是找到最小的金币花费,使得获得的分数至少为 kk。
算法步骤
-
理解问题:机器人可以从起点向右跳,每次跳的距离为 d 或在花费一定金币后增加的灵活性范围内。目标是找到最小的金币花费,使得总分数至少为 k。
-
预处理:首先,我们需要根据给定的格子位置和分数,构建一个数组或列表,其中每个元素代表一个格子的位置和分数。
-
动态规划:使用动态规划来计算在不同金币花费下的最大分数。设 dp[g]表示花费 g 金币时可以获得的最大分数。我们需要初始化 dp[0]为在不花费金币时的最大分数,然后逐步增加金币花费,更新 dp 数组。
-
更新 dpdp 数组:对于每个 g,我们需要考虑所有可能的弹跳距离,并计算在这些距离下可以获得的最大分数。这涉及到遍历所有格子,并尝试所有可能的弹跳组合。
-
二分查找:由于我们需要找到最小的 g 使得 dp[g]≥kdp[g]≥k,我们可以使用二分查找来优化搜索过程。
-
边界条件:确保在计算过程中考虑边界条件,例如当 g≥dg≥d 时,机器人可以跳任何距离。
-
输出结果:如果找到了满足条件的最小 g,则输出这个值;如果没有这样的 g,则输出 −1。
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;int minGoldNeeded(int n, int d, int k, vector<pair<int, int>>& grid) {// 将格子按照位置排序sort(grid.begin(), grid.end());// 计算最大可能的金币花费int maxGold = 0;for (int i = 0; i < n; ++i) {maxGold = max(maxGold, grid[i].first);}// 使用一个哈希表来存储每个位置的最大分数unordered_map<int, int> dp;dp[0] = 0; // 0金币时的分数是0// 遍历每个格子,更新dp表for (int i = 0; i < n; ++i) {int pos = grid[i].first;int score = grid[i].second;for (int g = maxGold; g >= 0; --g) {if (dp.find(g) != dp.end()) { // 如果这个金币花费是有效的int newScore = dp[g] + score;int newGold = g + pos;if (newGold > maxGold) continue; // 如果新金币花费超过最大值,则跳过dp[newGold] = max(dp[newGold], newScore);}}}// 使用二分查找找到最小的金币花费int left = 0, right = maxGold;while (left < right) {int mid = left + (right - left + 1) / 2;if (dp.find(mid) != dp.end() && dp[mid] >= k) {right = mid - 1;} else {left = mid;}}// 如果找不到满足条件的金币花费,返回-1if (dp.find(left) == dp.end() || dp[left] < k) {return -1;}return left;
}int main() {int n = 7, d = 4, k = 10;vector<pair<int, int>> grid = {{2, 6}, {5, -3}, {10, 3}, {11, -3}, {13, 1}, {17, 6}, {20, 2}};int result = minGoldNeeded(n, d, k, grid);cout << result << endl;return 0;
}
相关文章:

跳房子(弱化版)
题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一。 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 n 个格子,这些格子都在同一条直线上。每个格子内…...

ubuntu22 安装 minikube
在Ubuntu 22上安装Minikube,你可以按照以下步骤进行: 安装依赖: 更新系统并安装必要的依赖项: sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl安装Docker: Minikube可以使用D…...

STM32 | 超声波避障小车
超声波避障小车 一、项目背题 由于超声波测距是一种非接触检测技术,不受光线、被测对象颜色等的影响,较其它仪器更卫生,更耐潮湿、粉尘、高温、腐蚀气体等恶劣环境,具有少维护、不污染、高可靠、长寿命等特点。因此可广泛应用于…...

打造旅游卡服务新标杆:构建SOP框架与智能知识库应用
随着旅游业的蓬勃兴起,旅游卡产品正逐渐成为市场的焦点。为了进一步提升服务质量和客户体验,构建一套高效且标准化的操作流程(SOP)变得尤为重要。本文将深入探讨如何构建旅游卡的SOP框架,并介绍如何利用智能知识库技术…...

通过脚本,发起分支合并请求和打tag
#!/bin/bash # Set GitLab API URL and access token GITLAB_API_URL"http://IP/api/v4" ACCESS_TOKEN"Token秘钥" # Define repository IDs declare -A repo_ids( ["gitIP:kingmq/client.git"]"123" ["gitIP:kingmq/s…...

【视频讲解】Python深度神经网络DNNs-K-Means(K-均值)聚类方法在MNIST等数据可视化对比分析...
全文链接:https://tecdat.cn/?p38289 分析师:Cucu Sun 近年来,由于诸如自动编码器等深度神经网络(DNN)的高表示能力,深度聚类方法发展迅速。其核心思想是表示学习和聚类可以相互促进:好的表示会…...

网络安全在线网站/靶场:全面探索与实践
目录 1. CyberPatriot 简介 功能与特点 适用人群 2. Hack The Box 简介 功能与特点 适用人群 3. OverTheWire 简介 功能与特点 适用人群 4. VulnHub 简介 功能与特点 适用人群 5. PortSwigger Web Security Academy 简介 功能与特点 适用人群 6. TryHackM…...

Ceph 中Crush 算法的理解
Crush(Controlled Replication Under Scalable Hashing)算法是一种可扩展的、分布式的副本数据放置算法,广泛用于存储系统中,特别是Ceph分布式存储系统中。以下是对CRUSH算法的详细解释: 一、算法原理 CRUSH算法根据…...

D70【 python 接口自动化学习】- python 基础之数据库
day70 Python综合实践 学习日期:20241116 学习目标: MySQL 数据库 Q -- Python 综合实践 学习笔记: 案例需求 数据内容 DDL定义 总结 1. 使用Python实现读取写入数据库操作 ps.今天去看航展了,歼20简直不要太快,明…...

C# LINQ数据访问技术
文章目录 1.LINQ 的基本概念1.1 LINQ 的优势1.2 LINQ 数据访问的方式 2.LINQ 基本操作2.1 查询语法2.2 方法语法 3.LINQ 常用查询方法3.1 Where3.2 Select3.3 OrderBy / OrderByDescending3.4 GroupBy3.5 Join3.6 Aggregate 4.LINQ 查询示例4.1 LINQ to Objects4.2 LINQ to SQL…...

【JavaSE线程知识总结】
多线程 一.创建线程1.多线程创建方式一(Thread)2.多线程创键方式二(Runnable)3.线程创建方式三 二.线程安全问题解决办法1.使用同步代码块synchornized 2 .使用Lock解决线程安全问题 三.总结 线程就是程序内部的一条执行流程 一.创建线程 常用的方法 Thread.currentThread()…...

FreeRTOS内存管理
1. 为什么要自己实现内存管理 对于内核对象,可以使用时分配,不使用时释放C语音的库函数不适应与FreeRTOS: 实现过于复杂,占用空间大并非线程安全的运行不确定性:每次运算时间不确定内存碎片化不太编译器配置不同调试难 2. 堆栈…...

利用服务工作线程serviceWorker缓存静态文件css,html,js,图片等的方法,以及更新和删除及版本控制
Service Worker 是一种运行在浏览器背后的独立线程,可以用来处理推送通知、后台同步、缓存等任务。以下是使用 Service Worker 来缓存图片的一个基本示例: 1、注册 Service Worker: 首先,你需要在你的 JavaScript 文件中注册 Service Worker。…...

MuMu模拟器安卓12安装Xposed 框架
MuMu模拟器安卓12安装Xposed 框架 当开启代理后,客户端会对代理服务器证书与自身内置证书展开检测,只要检测出两者存在不一致的情况,客户端就会拒绝连接。正是这个原因,才致使我们既没有网络,又抓不到数据包。 解决方式: 通过xposed框架和trustmealready禁掉app里面校验…...

高级数据结构——hash表与布隆过滤器
文章目录 hash表与布隆过滤器1. hash函数2. 选择hash函数3. 散列冲突3.1 负载因子3.2 冲突解决3. STL中的散列表 4. 布隆过滤器4.1 背景1. 应用场景2. 常见的处理场景: 4.2 布隆过滤器构成4.3 原理4.4 应用分析4.5 要点 5. 分布式一致性hash5.1 缓存失效问题 6. 大数…...

【网络】什么是交换机?switch
交换机(Switch)意为“开关”,是一种用于电(光)信号转发的网络设备。以下是关于交换机的详细解释: 一、交换机的基本定义 功能:交换机能为接入交换机的任意两个网络节点提供独享的电信号通路&am…...

软件测试 —— 自动化基础
目录 前言 一、Web 自动化测试 1.什么是 Web 自动化测试 2.驱动 3.安装驱动管理 二、Selenium 1.简单 web 自动化测试示例 2.工作原理 三、元素定位 1.cssSelector 2.XPath 四、操作测试对象 1.点击/提交对象 2.模拟按键输入 3.清除文本内容 4.获取文本信息 5.…...

深入解析 OpenHarmony 构建系统-4-OHOSLoader类
在OpenHarmony操作系统构建过程中,OHOSLoader类扮演着至关重要的角色。这个类负责加载和解析构建配置,生成必要的构建文件,并确保构建过程的顺利进行。本文将深入分析OHOSLoader类的实现细节,揭示其如何管理构建配置,并…...

【Android、IOS、Flutter、鸿蒙、ReactNative 】实现 MVP 架构
Android Studio 版本 Android Java MVP 模式 参考 模型层 model public class User {private String email;private String password;public User(String email, String password) {this.email = email;this.password = password;}public String getEmail() {return email;}…...

排序算法(基础)大全
一、排序算法的作用: 排序算法的主要作用是将一组数据按照特定的顺序进行排列,使得数据更加有序和有组织。 1. 查找效率:通过将数据进行排序,可以提高查找算法的效率。在有序的数据中,可以使用更加高效的查找算法&…...

Pytest从入门到精通
一、pytest单元测试框架 (1)什么是单元测试框架 单元测试是指在软件开发当中,针对软件的最小单位(函数,方法)进行正确性的检查测试。 (2)单元测试框架 java : junit和testng python : unittest和pytest (3)单元测试框架主要做什么? 1.测试发现:从多个文件里面去找到我们测试…...

《C++ 实现生成多个弹窗程序》
《C 实现生成多个弹窗程序》 在 C 编程中,我们可以利用特定的系统函数来创建弹窗,实现向用户展示信息等功能。当需要生成多个弹窗时,我们可以通过循环结构等方式来达成这一目的。 一、所需头文件及函数介绍 在 Windows 操作系统环境下&#…...

react 中 useRef Hook 作用
useRef是一个非常实用的钩子函数 一、访问和操作 DOM 元素 1. 获取 DOM 元素引用 1.1 基本原理 通过 useRef 我们可以直接操作 DOM 元素 1.2 代码示例 import React, { useRef, useEffect } from "react";const InputFocusComponent () > {const inputRef …...

Scala-键盘输入(StdIn)-用法详解
Scala 在 Scala 中,进行 键盘输入 主要通过 scala.io.StdIn 包来实现。 StdIn 提供了几个方法,用于从用户的键盘输入中读取不同类型的数据,如字符串、整数、浮点数等。 常用的输入方法有 readLine()、readInt()、readDouble()、readShort(…...

力扣(LeetCode)283. 移动零(Java)
White graces:个人主页 🙉专栏推荐:Java入门知识🙉 🐹今日诗词:雾失楼台,月迷津渡🐹 ⛳️点赞 ☀️收藏⭐️关注💬卑微小博主🙏 ⛳️点赞 ☀️收藏⭐️关注💬卑微小博主…...

ESP32C3单片机使用笔记---烧录MicroPython
使用MicroPython在ESP32C3单片机上编程,首先需要将MicroPython运行环境烧录到ESP32C3的Flash中去,步骤如下: 1.下载esptool烧录工具,下载地址: https://github.com/espressif/esptool 直接使用git clone git clone…...

Matter1.4重磅来袭,智能家居进入“互联”新纪元
近日,连接标准联盟(CSA)正式宣布推出最新的Matter1.4标准版本,并更新了一系列“史诗级”的增强功能,旨在提升现有智能家居之间的互操作性与兼容性,为智能家居用户带来更流畅的使用体验。 华普微,…...

tdengine学习笔记
官方文档:用 Docker 快速体验 TDengine | TDengine 文档 | 涛思数据 整体架构 TDENGINE是分布式,高可靠,支持水平扩展的架构设计 TDengine分布式架构的逻辑结构图如下 一个完整的 TDengine 系统是运行在一到多个物理节点上的,包含…...

机器学习-36-对ML的思考之机器学习研究的初衷及科学研究的期望
文章目录 1 机器学习最初的样子1.1 知识工程诞生(专家系统)1.2 知识工程高潮期1.3 专家系统的瓶颈(知识获取)1.4 机器学习研究的初衷2 科学研究对机器学习的期望2.1 面向科学研究的机器学习轮廓2.2 机器学习及其应用研讨会2.3 智能信息处理系列研讨会2.4 机器学习对科学研究的重…...

Linux 进程信号的产生
目录 0.前言 1. 通过终端按键产生信号 1.1 CtrlC:发送 SIGINT 信号 1.2 Ctrl\:发送 SIGQUIT 信号 1.3 CtrlZ:发送 SIGTSTP 信号 2.调用系统命令向进程发信号 3.使用函数产生信号 3.1 kill 函数 3.2 raise 函数 3.3 abort 函数 4.由软件条件产…...