[刷题笔记] Luogu P1725 琪露诺
Description
若当前在\(pos\)位置,每次可以在\([pos+l,pos+r]\)区间内任选一个点跳。每跳到一个地方就可以获得这个地方的值,最后跳到位置\(pos \geq n\)即为结束,求如何跳才能使结束的时候获得的值最大?
Analysis
我们发现所有操作都是在一条链上完成的,显然若再次跳到这个位置时的值不如上次则此时继续跳对答案是没有贡献的。也就是说局部最优解可以被利用。同时我们发现前面如何跳到了这个位置对于后面跳是没有影响的,符合无后效性,考虑dp。
我们发现每跳到一个点\(pos\),她对什么有贡献呢?显然是对\(\forall i\in [pos+l,pos+r]\)有贡献。具体地,若定义\(f_i\)表示前\(i\)个点的最大值,则满足:
\(f_i=max(f_i,f_{pos}+a_i)\)
补充:和上文同理满足\(\forall i\in [pos+l,pos+r]\),\(a_i\)指当前位置的值。
Explanation:每个点\(i\)都可以先跳到\(pos\)再跳到\(i\)(因为满足\(\forall i\in [pos+l,pos+r]\),显然一个点\(i\)可能会被访问很多次,因为很可能有很多个\(pos\)可以到\(i\),取max即可)
由于本题数据很水朴素dp就能过,先不写优化了awa
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 200010;
int n,l,r;
int f[2*N];
int a[2*N];
int ans = -1e9;
int main()
{
scanf("%d%d%d",&n,&l,&r);
for(int i=0;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(f,-0x3f,sizeof(f)); //由于有负数所以需要初始化为MINN
f[0] = 0; //依据题意第0为的值为0
for(int i=0;i<=n;i++) //枚举pos
{
for(int j=i+l;j<=i+r;j++) //每个pos对谁产生贡献?
{
f[j] = max(f[j],f[i]+a[j]);
}
}
for(int i=n;i<=n+r;i++) ans = max(ans,f[i]); //由于跳到n外也算离开,观察上面dp程序显然发现最多跳到n+r,取max即可
cout<<ans<<endl;
return 0;
}
本文作者:SXqwq,转载请注明原文链接:https://www.cnblogs.com/SXqwq/p/17624130.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!