H题
终别
https://ac.nowcoder.com/acm/contest/11216/H
题意:
使用魔法或者斩击消除数组。
题解:
- 假设这道没有魔法这项能力的话,
现在有一个数组,要如何使用最少次数的斩击才能使数组的每个数都消除?
4,7,8,3,1,0,4,5
首先可以想到,数组的第一个数必须要先消除,才能保证最优,其次是第二个数,再到第三个……,因此不使用魔法的话,只要进行贪心就能得到最少次数的斩击数。
- 将魔法这项技能加进来,假设将下面数组中的这两个数用魔法消除(数组中字体加粗的那两个):
4,7,8,3,1,0,4,5
求解最少斩击数,就应该是1 ~ 3和6 ~ 7(数组的下标从1开始)这两段的最少斩击数,对于求解这两段的最少斩击数,可以采用上面的贪心去求解。
如果用魔法消除的是ai和ai+1 ,那么斩击数就是数组1~i−1和 i+2 ~ n区间的最少斩击数,对于数组的斩击数,我们是可以预处理出来的,使用per数组代表1 ~ n的斩击数,sur数组代表n ~ 1的斩击,所以这题的结果就是min(per[i−1],sur[i+2])。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+100;
typedef long long ll;
ll pre[N],sur[N],a[N],b[N];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]),b[i]=a[i];
if(n<=2)
{
puts("0");
return 0;
}
for(int i=1;i<=n;i++)
{
if(a[i]>0)
{
pre[i]=pre[i-1]+a[i];
a[i+1]-=a[i];a[i+2]-=a[i];
}
else pre[i]=pre[i-1];
}
for(int i=n;i>=2;i--)
{
if(b[i]>0)
{
sur[i]=sur[i+1]+b[i];
b[i-1]-=b[i];b[i-2]-=b[i];
}
else sur[i]=sur[i+1];
}
/*for(int i=1;i<=n;i++)
printf("%4d ",pre[i]);printf("\n");
for(int i=1;i<=n;i++)
printf("%4d ",sur[i]);printf("\n");*/
ll ans=pre[n];
for(int i=1;i<=n;i++)
ans=min(ans,pre[i-1]+sur[i+2]);
printf("%lld\n",ans);
return 0;
}