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+t−1位、i+t−2i+t-2i+t−2位……
-
所以对于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;
}

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

被折叠的 条评论
为什么被折叠?



