【NOIP2017提高A組集訓10.21】Dark
技術標籤:題解
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}
fi−1轉移。由於要將連續兩個取完,即
f
i
=
f
i
−
1
+
a
i
f_i=f_{i-1}+a_i
fi=fi−1+ai。
2.
f
i
−
2
f_{i-2}
fi−2轉移。表示空一個取,即
f
i
=
f
i
−
2
+
a
i
f_i=f_{i-2}+a_i
3.
f
i
−
3
f_{i-3}
fi−3轉移。表示空兩個取,即
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=fi−3+max(ai−1,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))
但你會發現一些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]));
}