【题解】P2627 [USACO11OPEN] Mowing the Lawn G 题解

P2627

    • 题目
      • 题目描述
      • 输入格式
      • 输出格式
      • 样例 #1
        • 样例输入 #1
        • 样例输出 #1
  • 解题思路
    • 分析
    • Code
    • 更多方法


题目

原题链接

[USACO11OPEN] Mowing the Lawn G

题目描述

在一年前赢得了小镇的最佳草坪比赛后,Farmer John 变得很懒,再也没有修剪过草坪。现在,新一轮的最佳草坪比赛又开始了,Farmer John 希望能够再次夺冠。
然而,Farmer John 的草坪非常脏乱,因此,Farmer John 只能够让他的奶牛来完成这项工作。Farmer John 有 N N N 1 ≤ N ≤ 1 0 5 1\le N\le 10^5 1N105)只排成一排的奶牛,编号为 1 … N 1\ldots N 1N。每只奶牛的效率是不同的,奶牛 i i i 的效率为 E i E_i Ei 0 ≤ E i ≤ 1 0 9 0\le E_i\le 10^9 0Ei109)。
靠近的奶牛们很熟悉,因此,如果 Farmer John安排超过 K K K 只连续的奶牛,那么,这些奶牛就会罢工去开派对 。因此,现在 Farmer John 需要你的帮助,计算 FJ 可以得到的最大效率,并且该方案中没有连续的超过 K K K 只奶牛。

输入格式

第一行:空格隔开的两个整数 N N N K K K
第二到 N + 1 N+1 N+1 行:第 i + 1 i+1 i+1 行有一个整数 E i E_i Ei

输出格式

第一行:一个值,表示 Farmer John 可以得到的最大的效率值。

样例 #1

样例输入 #1
5 2
1
2
3
4
5
样例输出 #1
12

解题思路

分析

我们转换一下题目,即给定一个序列 a 1 , 2 , 3 , … , n a_{1,2,3, \dots ,n} a1,2,3,,n,和一个整数 k k k,要求每 k k k 个数中最少删除一个数。
考虑DP:
f [ i ] f[i] f[i] 表示算到 a i a_i ai 时的最小删除和。
则很容易得转移方程:
f [ i ] = min ⁡ ( f [ i − 1 ] , f [ i − 2 ] , … , f [ i − k + 1 ] ) + E [ i ] f[i]=\min{(f[i-1],f[i-2],\dots,f[i-k+1])}+E[i] f[i]=min(f[i1],f[i2],,f[ik+1])+E[i]
初始化 f [ i ] f[i] f[i] 为正无穷大, f [ 1 ] = E [ 1 ] f[1]=E[1] f[1]=E[1]

时间复杂度: O ( N K ) = O ( N 2 ) O(NK)=O(N^2) O(NK)=O(N2)

考虑优化:
显然,对于 min ⁡ ( f [ i − 1 ] , f [ i − 2 ] , … , f [ i − k + 1 ] ) \min{(f[i-1],f[i-2],\dots,f[i-k+1])} min(f[i1],f[i2],,f[ik+1]),可以用单调队列维护。
单调队列不会?点这里。
所以这题我们就做出来了。

Code

#include
#define int long long
const int N=1e6+1;
int n,m,a[N],q[N],f[N],s[N],o;
signed main()
{
	scanf("%lld%lld",&n,&m);
	m++;
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]),o+=a[i];
	int h=1,t=0;
	int ans=1e18;
	for(int i=1;i<=n;i++)
	{
		while(h<=t&&i-m>q[h])
			h++;
		while(h<=t&&f[q[t]]>=f[i-1])
			t--;
		q[++t]=i-1;
		f[i]=f[q[h]]+a[i];			
	}
	for(int i=n-m+1;i<=n;i++)
		ans=std::min(ans,f[i]);
	printf("%lld",o-ans);
}

更多方法

更多方法

你可能感兴趣的:(C++题解,算法,c++)