【NOIP2017提高A组集训10.21】Dark

题目描述

Description

LichKing 希望收集邪恶的黑暗力量,并依靠它称霸世界。
世间的黑暗力量被描述成一个长度为N 的非负整数序列{Ai},每次它可以选择这个序列中的两个相邻的正整数,让他们的值同时减一并获得一点邪恶力量,直到不存在满足条件的数。
然而你不希望他能够得逞,所以你会使得他收集的能量尽可能少。

Input

N
A1 A2 … AN

Output

输出一行一个整数,表示答案。

Sample Input

10
2 0 1 2 0 0 0 0 0 0

Sample Output

1

Data Constraint

在这里插入图片描述

思路

这题可以考虑用dp来做。
f i f_i fi表示 i i i这个位置要取完且 1 1 1~ i i i都合法。
因为是两个连续的数,所以可以考虑从三个位置转移。
1. f i − 1 f_{i-1} fi1转移。由于要将连续两个取完,即 f i = f i − 1 + a i f_i=f_{i-1}+a_i fi=fi1+ai
2. f i − 2 f_{i-2} fi2转移。表示空一个取,即 f i = f i − 2 + a i f_i=f_{i-2}+a_i fi=fi2+ai
3. f i − 3 f_{i-3} fi3转移。表示空两个取,即 f i = f i − 3 + m a x ( a i − 1 , a i ) f_i=f_{i-3}+max(a_{i-1},a_i) fi=fi3+max(ai1,ai)。因为必须i和i-1都取完,才能够保证i-2和i-1不连着。
将上述转移式整合一下,就可得
f i = m i n ( m i n ( f i − 1 + a i , f i − 2 + a i ) , f i − 3 + m a x ( a i − 1 , a i ) ) f_i=min(min(f_{i-1}+a_i,f_{i-2}+a_i),f_{i-3}+max(a_{i-1},a_i)) fi=min(min(fi1+ai,fi2+ai),fi3+max(ai1,ai))
但你会发现一些interesting的问题
如:
……4 3 6 2……,当运行到6时,你会发现不可能取6个,最多只能取5个,那会不会影响答案呢?
并不会,因为错误的计算算出来的答案会多,自然会比正确情况的答案多,而正解又包含在我们推导的三个情况里,所以正解会筛掉错误的计算。

Code

#include<cstdio>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
int n,a[100005],f[100005];
int main()
{
    
    
	fre(dark);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	f[1]=a[1],f[2]=a[2];
	for(int i=3;i<=n;i++)
		f[i]=min(min(f[i-1]+a[i],f[i-2]+a[i]),f[i-3]+max(a[i],a[i-1]));
	printf("%d",min(f[n-1],f[n]));
}

猜你喜欢

转载自blog.csdn.net/weixin_46830417/article/details/111755331