题意:不能挑选连续的m只奶牛去工作,求最大效率。
状态表示:f[i]表示从第1头奶牛开始到第i头奶牛合理工作的最大效率。
状态转移:1、第i头奶牛不工作,那么效率就是f[i - 1]
2、第i头奶牛工作,那么在第[i - m , i - 1]中必须有一头奶牛不工作, 假设第j头牛不工作那么效率为 :第j + 1头牛到第i头牛的效率和加上f[j - 1];利用前缀和求解第j + 1头牛到第i头牛的效率和。即f[i] = max{f[j - 1] + S[i] - S[i - j]},(i - m <= j <= i - 1),由于i为固定值,因此即为f[i] = max{f[j - 1] - S[i - j]} + S[i],只需用单调队列维护在i的前m个奶牛中,f[j - 1] - S[i - j]的最大值即可。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100010;
int n, m;
ll s[N];
ll f[N];
int q[N];
ll g(int i)
{
return f[i - 1] - s[i];
}
int main(void)
{
scanf("%d%d" ,&n, &m);
for(int i = 1; i <= n; i ++)
{
scanf("%d", &s[i]);
s[i] += s[i - 1];
}
int hh = 0, tt = 0;
for(int i = 1; i <= n; i ++)
{
if(q[hh] < i - m) hh ++;
f[i] = max(f[i - 1], g(q[hh]) + s[i]);//先用后维护,与第i头奶牛的信息无关
while(hh <= tt && g(q[tt]) <= g(i)) tt --;
q[++ tt] = i;
}
printf("%lld\n", f[n]);
return 0;
}
也可以用烽火传递的方法来做这道题,转化为在连续m头奶牛中必须至少有一头奶牛休息,求出这些奶牛休息的最小效率,最后用效率总和捡起这个最小效率即为答案。