Description
“第七套广播体操,原地踏步——走!”
众所周知,跳蚤们最喜欢每天早起做早操,经常天还没亮就齐刷刷地站在操场做着反复纵跳热热身。跳晚国在研制三星 note7 的时候注意到了这点,于是他们打算让炸弹更快地引爆,这样就可以消灭更多早起的跳蚤。
三星 note7 的主板可以看作是由 (2n+1)×(2n+1)(2n+1)×(2n+1) 个中继器构成的,某些中继器会有导线连在一起,左上角和右下角的中继器分别连着电源的正负极。
电流流过一根导线的时间可忽略不计,但当电流经过中继器时,会延缓一段时间再从中继器流出。这个时间只跟该中继器本身有关,我们把这段时间的长度称为中继器的延时值。
这些中继器由导线连接围成一个一个的层,同个层的中继器的种类都一样,而不同层的种类都不一样,可以发现总共有 n+1n+1 层。当 n=4n=4 时,主板大概长这样:
n≤10^5
对于所有数据,保证每个数都是不超过 10^9 的正整数。
Analysis
rzOmyyOrz
这题可以算是个半结论题,贪心解决
结论
- 只可能往右或往下走(较容易想到,感性易证)
- 可以把矩阵变成 ◥ <script type="math/tex" id="MathJax-Element-135">◥</script>的样子,即抹去对角线下面(显然)
- 最优方案必定是从左上角走到(i,i),再在第i层绕一圈,再从该层的右下角走到(2n+1,2n+1),i可以枚举(由结论1,再深入分析可得)
j--+@@@
@@|@@@
@|@@@
i@@@
@@@
@@
@
由结论3,我们就可以递推出(1,1)到(i,i)的最短时间。
那么f[i]=Min(f[j]+上图中经过的点的时间和)
而且,这里又有一个性质
决策是单调的,换句话说,已经被踢掉的某个j是不可能重新再成为最优决策
一道很好的贪心题
所以简单搞搞啦,500多B就没啦。
Code
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
typedef long long ll;
const int N=100010;
const ll INF=1000000000000000000;
ll n,a[N],b[N],sum[N];
int main()
{
scanf("%d",&n);
fd(i,n,0) scanf("%lld",&a[i]);
fd(i,n,0) sum[i]=sum[i+1]+a[i];
ll k=0,ans=INF;
b[0]=a[0];
fo(i,1,n)
{
ll t1=b[k]+(i-k)*a[k]+sum[k+1]-sum[i+1],t2=b[i-1]+a[i-1]+a[i];
if(t2<t1) t1=t2,k=i-1;
b[i]=t1;
}
fo(i,0,n) ans=min(ans,b[i]*2+a[i]*((n-i)*4-1));
printf("%lld",ans);
return 0;
}