UOJ #244. 【UER #7】短路

来源:互联网 发布:英汉词典软件下载 编辑:程序博客网 时间:2024/05/16 11:10

题目链接

UOJ #244. 【UER #7】短路

题目描述

第七套广播体操,原地踏步——走!”
众所周知,跳蚤们最喜欢每天早起做早操,经常天还没亮就齐刷刷地站在操场做着反复纵跳热热身。跳晚国在研制三星 note7 的时候注意到了这点,于是他们打算让炸弹更快地引爆,这样就可以消灭更多早起的跳蚤。
三星 note7 的主板可以看作是由 (2n+1)×(2n+1)(2n+1)×(2n+1) 个中继器构成的,某些中继器会有导线连在一起,左上角和右下角的中继器分别连着电源的正负极。
电流流过一根导线的时间可忽略不计,但当电流经过中继器时,会延缓一段时间再从中继器流出。这个时间只跟该中继器本身有关,我们把这段时间的长度称为中继器的延时值。
这些中继器由导线连接围成一个一个的层,同个层的中继器的种类都一样,而不同层的种类都不一样,可以发现总共有 n+1n+1 层。当 n=4n=4 时,主板大概长这样:
跳晚们打算再加几根导线将某些中继器连接起来.凭借发达的重工业,他们能生产出无数条导线。但由于主板的限制,他们的导线只能和主板四周的边平行,且其长度只够连接相邻两个中继器。
现在他们想知道,他们改造的三星 note7 的电源正极流出的电流能在多短的时间到达电源负极从而造成短路,这样电池就会释放出巨大的能量摧毁跳蚤国的有生力量了。
请参考输入格式和样例配图来更好地理解题意。

输入格式

第一行一个正整数 nn。
第二行 n+1n+1 个正整数 a0,a1,…,ana0,a1,…,an,表示从内到外每层的中继器的延时值,单位为秒。其中,第 ii 行第 jj 列的中继器的延时值为(1≤i,j≤n1≤i,j≤n)
amax(|i−n−1|,|j−n−1|)
amax(|i−n−1|,|j−n−1|)

输出格式

输出一行一个数表示改造后的最短引爆时间。
C/C++ 输入输出 long long 时请用 %lld。C++ 可以直接使用 cin/cout 输入输出。
样例一
input
1
1 2
output
9
样例二
input
9
9 5 3 7 6 9 1 8 2 4
output
69

Solution

其实它的题解已经很明确了,不过还是有一点不太清楚的地方
先给出结论:最短路必定是走到某个(i,i)点,即某一圈的左上角,然后绕半圈,走到右下角,在沿原来的路线走回去,因为是对称的
证明去看UOJ题解
题解上说要一个前缀最小值,为什么呢?
其实记录的是前缀最小值的位置,因为不论怎么走,经过的电路板数量是一样的,而且如果走到第x层,则x之前每一层都要被走过,那么一定在延时最小的那一层多走一些,这样类似贪心的求出策略就行了
如何计算答案?去数数

Code

#include<cstdio>#include<algorithm> #define ll long long#define fo(i,a,b) for(ll i=a;i<=b;i++)#define N 100100using namespace std;ll a[N],f[N],m[N],mn[N],s[N],n;int main(){    scanf("%lld",&n);    fo(i,1,n+1) scanf("%lld",&a[i]);    fo(i,1,(n+1)/2) swap(a[i],a[n-i+2]);    f[1]=a[1];ll ans=a[1]*(ll)(n*4+1);m[1]=a[1];s[1]=a[1];mn[1]=1;    fo(i,2,n+1)    {        s[i]=s[i-1]+a[i];if(a[i]<=m[i-1]) m[i]=a[i],mn[i]=i;else m[i]=m[i-1],mn[i]=mn[i-1];        int x=mn[i-1];        f[i]=f[x]+(i-x)*a[x]+s[i]-s[x];ans=min(ans,f[i]*2ll+a[i]*(4*(n-i)+3));    }    printf("%lld",ans);}
1 1