【JZOJ5948】 增援前线

在魂师过河的问题中,通过优化算法实现魂师数量最大化。每飞行L米需在荷叶上休息,荷叶有限且使用后沉没。算法通过动态规划找到最优路径,确保最多魂师能抵达对岸。

description

小 X 的国家正在遭受袭击,必须抽调一些魂师上前线增援。
到前线用时最短的路上有一条宽度为 N 米的河,而前来增援的魂师每飞行 L 米就必须在一片荷叶上休息一下,才能够继续飞行。当然,魂师们也可以选择没飞够 L 米就先休息一下,但不能一次飞超过 L 米。
距离河的一侧距离为i 的荷叶共有Ai 片,每片荷叶在有魂师停于上方休息后, 就会沉入水底,不能够再供其他魂师休息。
现在小 X 想要知道,至多有多少名魂师能够抵达前线。


analysis

  • 想要让尽可能多的人过河,那么走的距离就尽可能长

  • f[i]f[i]f[i]为第iii位的答案,那么我们一定尽可能先走到i+ti+ti+t位、i+t−1i+t-1i+t1位、i+t−2i+t-2i+t2位……

  • 所以对于nnn个位置每一个位置都O(t)O(t)O(t)暴力跳一次就好了

  • 理论上这个暴力O(nt)O(nt)O(nt)的,但过了


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 200005
#define INF 1000000007
#define reg register int
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))

using namespace std;

int a[MAXN],f[MAXN];
int n,l,ans;

O3 inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0' || '9'<ch){if (ch=='-')f=-f;ch=getchar();}
    while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
O3 inline int max(int x,int y){return x>y?x:y;}
O3 inline int min(int x,int y){return x<y?x:y;}
O3 int main()
{
	freopen("reinforce.in","r",stdin);
	freopen("reinforce.out","w",stdout);
	n=read(),l=read();
	fo(i,1,n-1)a[i]=read();
	fo(i,1,l)f[i]=a[i];
	a[n]=INF;
	fo(i,1,n-1)
	{
		fd(j,i+l,i+1)
		if (a[j]-f[j]>=f[i]) 
		{
			f[j]+=f[i];
			f[i]=0;
			break;
		}
		else f[i]-=a[j]-f[j],f[j]=a[j];
	}
	printf("%d\n",f[n]);
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值