CSP历年复赛题-P1095 [NOIP2007 普及组] 守望者的逃离
原题链接:https://www.luogu.com.cn/problem/P1095
题意解读:在有限的时间内,通过跑步或者闪烁两种方式,能跑出的最远距离是多少,以及是否能跑出出口。
解题思路:
1、贪心法
每一秒钟,都有两种选择:跑步(17米)、闪烁(60米,前提是蓝够10点,否则等待1s恢复4点蓝)
经过计算,恢复足够的蓝到闪烁需要3.5s,而3.5s跑步可以跑出59.5
因此,在时间充分的情况下,闪烁以及等待回蓝是最佳方案,但是在最后的几秒,跑步才是更佳!
所以,可以枚举每一秒,跑步、闪烁两种方式同步进行,计算各自前进的距离,下一秒跑步的距离要以之前两种方案跑出最远的距离为基准(闪烁跑得远就用闪烁,否则就跑步)
100分代码:
#include <bits/stdc++.h>
using namespace std;
int m, s, t;
int dist1; //跑步的距离
int dist2; //闪烁的距离
int main()
{
cin >> m >> s >> t;
for(int i = 1; i <= t; i++)
{
dist1 += 17; //跑步方式
if(m >= 10) //闪烁方式
{
dist2 += 60;
m -= 10;
}
else
{
m += 4;
}
dist1 = max(dist1, dist2); //如果这一秒闪烁更远,跑步方式就改成闪烁
if(dist1 >= s)
{
cout << "Yes\n" << i;
return 0;
}
}
cout << "No\n" << dist1;
return 0;
}
2、动态规划
状态表示:f[i]表示经过i秒能跑出的最大距离
状态转移:
如果是闪烁:
蓝够:f[i] = f[i-1] + 60,蓝减10
蓝不够:f[i] = f[i-1],蓝加4
如果是跑步:
f[i] = f[i - 1] + 17
可以第一轮枚举时间使用闪烁跑一遍,再枚举一遍时间用跑步补充,比较两者谁更远
f[i] = max(f[i],f[i-1] + 17)
初始化:f[0] = 0
结果:第一个f[i] > s,如果没有最远距离就是f[t]
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 300005;
int m, s, t;
int f[N]; //f[i]为前i秒最多跑出的距离
int main()
{
cin >> m >> s >> t;
for(int i = 1; i <= t; i++)
{
if(m >= 10) f[i] = f[i-1] + 60, m -= 10;
else f[i] = f[i-1], m += 4;
}
for(int i = 1; i <= t; i++)
{
f[i] = max(f[i], f[i-1] + 17);
}
for(int i = 1; i <= t; i++)
{
if(f[i] >= s)
{
cout << "Yes\n" << i;
return 0;
}
}
cout << "No\n" << f[t];
return 0;
}
分类:
CSP-J复赛真题解析
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?