题目
题解思路
如果没有魔法,就从1开始有多少斩多少。斩到最后全部结束就是答案。
但是有魔法的存在就不好处理了。
我们必须贪心出最优的魔法攻击位置。
一开始想着最大的地方,但是这个地方可能有很多个。
这里用了类似dp 的思想。
定义两个前缀后缀和,代表 从 1 到 n 和 从 n 到 1 的最小斩击数 k1[] k2[]。
如果我们在i处使用魔法。
那么答案就是 k1[i-1] + k2[i+2]
这样我们只需从1开始走一遍取最小的ans即可。
类似dp 的贪心。
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
using namespace std;
const int INF = 0x3f3f3f3f;
int a[1000100] ;
int b[1000100] ;
long long ms[1000100] ;
long long ks[1000100] ;
int main ()
{
ios::sync_with_stdio(false);cin.tie(0);
int n ;
cin >> n ;
for (int i = 1 ; i <= n ; i++ )
{
cin >> a[i] ;
b[i] = a[i] ;
}
if ( n <= 2 )
{
cout << "0\n" ;
return 0 ;
}
for ( int i = 1 ; i <= n ; i++ )
{
if ( a[i] > 0 )
{
ms[i] = a[i] + ms[i-1] ;
a[i+1] -= a[i] ;
a[i+2] -= a[i] ;
}else
ms[i] = ms[i-1] ;
}
for (int i = n ; i >= 2 ; i-- )
{
if ( b[i] > 0 )
{
ks[i] = ks[i+1] + b[i] ;
b[i-1] -= b[i] ;
b[i-2] -= b[i] ;
}else
ks[i] = ks[i+1] ;
}
long long ans = ms[n] ;
for ( int i = 1 ; i <= n ; i++ )
{
ans = min( ms[i-1] + ks[i+2] , ans ) ;
}
cout << ans << "\n" ;
return 0 ;
}