Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

CodeForces 1396C - Monster Invaders

首先扯一句题外话:B 出题人 ****。nmd 老子开学前一天打你午夜的比赛,还出个结论题糟蹋我比赛体验?还好把这个 C 做出来了,要不然玩完了。

洛谷题目页面传送门 & CF 题目页面传送门

题意见洛谷。

注意到一个 boss 的血量为 2,于是每一级最多会被强制离开 1 次。

于是考虑对于每一级决定是否被强制离开。设若不离开,那么第 i 级最少需要 xi 的时间打怪;若离开,那么第 i 级最少需要 yi 的时间打怪(这个 xi,yi 太好算了,显然可以 O(1),就不再赘述了)。显然,对于一种决定,总时间就是它们的打怪时间相加(虽然被强制离开的级别的打怪过程不是连续的,但也可以相加)加上走路的最小总时间。不妨来研究对于任意一个决定,走路的最优路线长什么样子。

若没有被强制离开的级别的话,最优路线显然是从 1 笔直走到 n。如果有的话,那么那些被强制离开的点要经过 2 次(这是显然的吧)。按原笔直路线经过它们的时候,它们只被经过了 1 次;要想来个第 2 次,肯定要回头;然后还要继续往前走啊,于是回头走到某处的时候还要再回头按原笔直路线走。于是很容易得出结论:最优路线一定是在笔直路线的基础上,有若干个不相交的区间多走了 2 遍,其中这些区间要覆盖所有的被强制离开的点。

细节:

  1. 每个区间的大小要 >1,因为 =1 的话就是原地打转,是不算经过多遍的;
  2. n 处不被强制离开的话,那么右端点为 n 的区间是只需要再多走 1 遍的,因为到达了左端点之后就没必要再回头了,游戏已经 win 了。

接下来就很容易设计出无后效性的 DP 了(在得出结论之前,瓶颈在于可以往两边跑,后效性消除不了)。dpi 表示考虑到第 i 级,停在第 i 级且前 i 级都打掉了时的最小打怪、额外走路总时间。边界:dp0=0,dp1=x1;目标:dpn+(n1)d。转移的话,考虑第 i 级是离开还是不离开两种选择:不离开简单要死;离开的话,显然 i 是最后一个重复走区间的右端点,于是枚举左端点。所以状态转移方程:

dpi=min

直接算是 \mathrm O\!\left(n^3\right) 的。里层 \sum 可以前缀和优化掉,剩下来简单拆一下 \min,发现就是个前缀 \min,稍微 two-pointers 简单维护一下就优化成了 \mathrm O(n)。注意,i=n 要特殊算,随便跑一下即可,不影响复杂度。

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=1000000;
int n;
int r1,r2,r3,d;
int a[N+1];
int dp[N+1];
int x[N+1],y[N+1];
int Sum[N+1];
signed main(){
	cin>>n>>r1>>r2>>r3>>d;
	for(int i=1;i<=n;i++)scanf("%lld",a+i);
	for(int i=1;i<=n;i++){
		x[i]=a[i]*min(r1,r3)+r3;
		y[i]=min(r2+min(min(r1,r2),r3),a[i]*min(r1,r3)+min(r1,r2)+min(min(r1,r2),r3));
		Sum[i]=Sum[i-1]+min(x[i],y[i]);
//		cout<<x[i]<<" "<<y[i]<<"\n";
	}
	int mn=inf;
	dp[1]=x[1];
	for(int i=2;i<n;i++){
		mn=min(mn,dp[i-2]-Sum[i-2]-2*(i-1)*d);
		dp[i]=min(dp[i-1]+x[i],mn+Sum[i]+2*i*d);
//		cout<<dp[i]<<"\n";
	}
	dp[n]=dp[n-1]+x[n];
	for(int i=0;i<=n-2;i++)
		dp[n]=min(dp[n],dp[i]+Sum[n]-Sum[i]+2*n*d-2*(i+1)*d),
		dp[n]=min(dp[n],dp[i]+Sum[n-1]-Sum[i]+x[n]+n*d-(i+1)*d);
	cout<<dp[n]+(n-1)*d;
	return 0;
}
posted @   ycx060617  阅读(221)  评论(1编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法
点击右上角即可分享
微信分享提示