NC16850 [NOI1998]免费馅饼
题目
题目描述
SERKOI最新推出了一种叫做“免费馅饼”的游戏:游戏在一个舞台上进行。舞台的宽度为W格,天幕的高度为H格,游戏者占一格。开始时游戏者站在舞台的正中央,手里拿着一个托盘。下图为天幕的高度为4格时某一个时刻游戏者接馅饼的情景。
游戏开始后,从舞台天幕顶端的格子中不断出现馅饼并垂直下落。游戏者左右移动去接馅饼。游戏者每秒可以向左或向右移动一格或两格,也可以站在原地不动。
馅饼有很多种,游戏者事先根据自己的口味,对各种馅饼依次打了分。同时,在8-308电脑的遥控下,各种馅饼下落的速度也是不一样的,下落速度以格/秒为单位。
当馅饼在某一秒末恰好到达游戏者所在的格子中,游戏者就收集到了这块馅饼。
写一个程序,帮助我们的游戏者收集馅饼,使得所收集馅饼的分数之和最大。
输入描述
第一行是用空格隔开的两个正整数,分别给出了舞台的宽度W(1到99之间的奇数)和高度H(1到100之间的整数)。
接下来依馅饼的初始下落时间顺序给出了所有馅饼的信息。每一行给出了一块馅饼的信息。由四个正整数组成,分别表示了馅饼的初始下落时刻(0到1000秒),水平位置、下落速度(1到100)以及分值。游戏开始时刻为0。从1开始自左向右依次对水平方向的每格编号。
输入文件中同一行相邻两项之间用一个或多个空格隔开
输出描述
第一行给出了一个正整数,表示你的程序所收集的最大分数之和。
其后的每一行依时间顺序给出了游戏者每秒的决策。输出0表示原地不动、1或2表示向右移动一步或两步、-1 或-2表示向左移动一步或两步。输出应持续到游戏者收集完他要收集的最后一块馅饼为止
示例1
输入
3 3 0 1 2 5 0 2 1 3 1 2 1 3 1 3 1 4
输出
12 -1 1 1
题解
知识点:线性dp。
显然不能模拟馅饼掉落,复杂度太高。考虑线性dp。
先找到可能掉到高度为 的地方馅饼,因为其他馅饼不可能被获得。在把时间作为一轴,横坐标作为水平位置,开一个数组 标记馅饼,一个馅饼如果在 时掉在水平位置 处,则其价值应该存于为 。这样就表达了整个题目的有效信息。
一个馅饼在 的当前仅当速度 整除实际掉落高度 时,才一定会在 时刻掉落到高度为 的地方从而有可能被吃掉,而我们只需要记录这种馅饼的价值在 即可。并且我们顺便可以把最晚落下的馅饼时间记录在 ,作为一个时间边界。
但是注意这里不只是求最大价值,还要求路径。
试想如果我们正推,从起点 开始,出发从第 秒推到 ,我们最后可以通过枚举 中的最大值作为答案,但是找路径推回去会有个问题,上一时刻同时存在很多个点是潜在上一个路径点,我们要保证逆推要推回唯一起点,但我们不确定这些点哪个点可行的,如果枚举这些点一定超时,当然你也可以一开始推的时候就只推起点能到的点,第一秒可能只推五个,第二秒可能推九个,其他点都是负无穷,大概也是可以,但这过于麻烦。我们完全可以从第 秒逆推回第 秒,然后答案就是 ,而路径直接从 逆推,无论推到哪里都是合法的,因为起点固定了。这样就做完了。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> #define ll long long using namespace std; int a[1107][107]; int dp[1107][107]; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int W, H; cin >> W >> H; int t, w, v, s; int maxt = 0; while (cin >> t >> w >> v >> s) { if ((H - 1) % v == 0) { a[t + (H - 1) / v][w] += s; maxt = max(maxt, t + (H - 1) / v); } } for (int i = maxt;i >= 0;i--) { for (int j = 1;j <= W;j++) { for (int k = -2;k <= 2;k++) { int pos = j + k; if (pos >= 1 && pos <= W) dp[i][j] = max(dp[i][j], dp[i + 1][pos] + a[i][j]); } } } int pre = W / 2 + 1; cout << dp[0][pre] << '\n'; for (int i = 1;i <= maxt;i++) { for (int j = -2;j <= 2;j++) {///不要忘了第一个要求是要走得到 int pos = pre + j; if (pos >= 1 && pos <= W && dp[i][pos] == dp[i - 1][pre] - a[i - 1][pre]) { cout << j << '\n'; pre = pos; break; } } } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16571642.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效