• 【BZOJ 2072】【POI2004】MOS


    问题描述

    一个夜晚一些旅行者想要过桥. 他们只有一个火把. 火把的亮光最多允许两个旅行者同时过桥. 没有火把或者多于2个人则不能过桥.每个旅行者过桥都需要特定的时间, 两个旅行者同时过桥时时间应该算较慢的那个. 我们想知道所有旅行者最少要花费多少时间才能全部过桥? Example 假如有4个人. 他们分别需要花费6,7,10,15分钟过桥.下图演示了他们如何使用44分钟全部过桥的,但他们能做得更快么?

    输入格式

    第一行一个数n 表示旅行者的总数, 1 ≤ n ≤ 100,000. 接下来n 行表示所有旅行者的过桥时间,时间从小到大排列,每个数不超过1,000,000,000.

    输出格式

    输出一个数表示最少过桥时间.

    样例输入

    4

    6

    7

    10

    15

    样例输出

    42

    题解

    算了十几分钟的样例。。。|ू・ω・` )

    样例算出来就发现,一个人过桥了,除非要给别人送火把,否则显然不会再回来。走得慢的人过桥的次数越少越好,走得快的人只能委屈一下多走几次给别人送火把。于是最优决策有两种,一种是走最快的人和走最慢的人过桥,走最慢的人留在对面,走最快的人把火把送回来;另一种是走最快的人和走次快的人过去,最快的人留在对面,走次快的人把火把送回来,然后走最慢的两个人过去。

    设f[i]表示剩下i个人没过桥所需的最少时间,a[i]表示第i个人过桥需要的时间

    f[i][j]=min(f[i+1]+a[i+1]+a[1], f[i+2]+a[2]*2+a[1]+a[i+2])

     1 #include <cstdio>
     2 #define ll long long
     3 int n,a[100005];
     4 ll f[100005];
     5 ll min(ll x,ll y)
     6 {
     7     return x<y?x:y;
     8 }
     9 int main()
    10 {
    11     int i,j;
    12     scanf("%d",&n);
    13     for (i=1;i<=n;i++) scanf("%d",&a[i]);
    14     if (n==1)
    15     {
    16         printf("%d",a[i]);
    17         return 0;
    18     }
    19     for (i=n-1;i>=2;i--)
    20     {
    21         f[i]=f[i+1]+a[i+1]+a[1];
    22         if (i<=n-2) f[i]=min(f[i],f[i+2]+a[2]*2+a[1]+a[i+2]);
    23     }
    24     printf("%lld",f[2]+a[2]);
    25     return 0;
    26 }
  • 相关阅读:
    在DataGrid中创建一个点击列名时的弹出式窗口
    利用自定义事件实现不同窗体间的通讯 C#篇
    用javascript实现禁用鼠标右键
    刷新页面时,防止滚动条上滚
    web服务编程
    数据库链接Connection和DataReader的关闭
    .NET的WEB商业应用架构所要解决的若干
    zblog屏蔽分类文章
    过年随想
    mysql数据库文件的真实的物理存储位置
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/9881620.html
Copyright © 2020-2023  润新知