愣是弄不出T3&T4了……
感觉T4有点像上次的T2灌水?但是要前缀和?
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。
所以开始设状态、推式子,但是1小时后无果,果然题目看似简单其实难得一批。
再看一下题目大意,每次选两个挨在一起得正整数,并且都减去他们中最小的那一个。然后问你要多少次可以消完。
所以,如何DP呢?考虑一维的线性方法:
首先是第一种
1 1
两个连着的都取的话,就变成了 0 0
式子
f
i
−
1
+
a
i
f_{i-1}+a_{i}
fi−1+ai
然后是第二种
中间隔了一个不取的话
1 0 1
成了
0 0 0
式子
f
i
−
2
+
a
i
f_{i-2}+a_{i}
fi−2+ai
最后是玄学的第三种
要是空两个取的话
1 0 0 1
要变成
0 0 0 0
i-1&i只能都去完,才能保证合法
所以式子
f
i
−
3
+
m
a
x
(
a
i
−
1
,
a
i
)
f_{i-3}+max(a_{i-1},a_{i})
fi−3+max(ai−1,ai)
但是,因为特殊性。我们要取到n+1这个位置才能找到正确的答案。
但是,我把这三个式子压成了一个式子。因为我们可以将整体的序列往后移2位,这样就只有一个式子啦。
#include<cstdio>
#include<cstring>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define cin(x) scanf("%lld",&x);
using namespace std;
long long n;
long long a[1000005],f[1000005];
long long max(long long x,long long y){if(x>y) return x;return y;}
long long min(long long x,long long y){if(x<y) return x;return y;}
int main()
{
fre(dark);
cin(n);n+=3;
for(long long i=3;i<n;++i) cin(a[i]);
for(long long i=3;i<=n;++i) f[i]=min(f[i-2]+a[i],f[i-3]+max(a[i-1],a[i]));
printf("%lld",f[n]);
return 0;
}
或者
#include<bits/stdc++.h>
using namespace std;
int n,i,j,a[1111111],f[1111111],ans;
int main()
{
freopen("dark.in","r",stdin);
freopen("dark.out","w",stdout);
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
f[1]=a[1];
f[2]=a[2];
for(i=3;i<=n;i++)
{
f[i]=min(f[i-1]+a[i],f[i-2]+a[i]);
f[i]=min(f[i],f[i-3]+max(a[i-1],a[i]));
}
ans=min(f[n],f[n-1]);
cout<<ans<<endl;
}