【UOJ #244】【UER #7 A】短路

28 篇文章 0 订阅

Description

“第七套广播体操,原地踏步——走!”

众所周知,跳蚤们最喜欢每天早起做早操,经常天还没亮就齐刷刷地站在操场做着反复纵跳热热身。跳晚国在研制三星 note7 的时候注意到了这点,于是他们打算让炸弹更快地引爆,这样就可以消灭更多早起的跳蚤。

三星 note7 的主板可以看作是由 (2n+1)×(2n+1)(2n+1)×(2n+1) 个中继器构成的,某些中继器会有导线连在一起,左上角和右下角的中继器分别连着电源的正负极。

电流流过一根导线的时间可忽略不计,但当电流经过中继器时,会延缓一段时间再从中继器流出。这个时间只跟该中继器本身有关,我们把这段时间的长度称为中继器的延时值。

这些中继器由导线连接围成一个一个的层,同个层的中继器的种类都一样,而不同层的种类都不一样,可以发现总共有 n+1n+1 层。当 n=4n=4 时,主板大概长这样:
这里写图片描述
n≤10^5
对于所有数据,保证每个数都是不超过 10^9 的正整数。

Analysis

rzOmyyOrz
这题可以算是个半结论题,贪心解决
结论

  1. 只可能往右或往下走(较容易想到,感性易证)
  2. 可以把矩阵变成 <script type="math/tex" id="MathJax-Element-135">◥</script>的样子,即抹去对角线下面(显然)
  3. 最优方案必定是从左上角走到(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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值