zoukankan      html  css  js  c++  java
  • 过桥

    在这里插入图片描述
    .
    .
    .
    .
    .
    分析

    最容易想到的一个贪心策略是:

    		让一个最快的人来回带人
    

    但是显然是错误的
    比如4个人:1 1 100000 100000
    最快的来回带的话要:1+1+100000+1+100000=200003

    但是如果先将1 1运过去的话,然后1回来,再让100000 100000一起过去,再让右边的1来回一趟,就只要1+1+100000+1+1=100004,这样显然更优

    所以第一种贪心的策略显然是不合理的,下面换种贪心策略:

    首先,慢的肯定是过了桥之后不回来了
    就上面那种情况,我们就是先将最快的两个带过去,
    然后快的一个过来,让两个慢的过去,然后让快的再来,…

    然而:
    如果是1 10000 10000 10000,答案又不对了(还是第一种策略优)

    结合以上两点,对于最慢的两个人我们有两种处理方法就是:
    1、让最快的人来回带
    2、让最快的两个人过去,再让最慢的两个一起过去,这样就减少了最慢的重复计算

    关于这个贪心策略的证明是:

    首先,过桥速度排在第三名之后的人不可能担任送回手电筒的任务,

    原因是不如速度第一和第二的人送回来得高效。这样,
    当前左岸速度最慢的人过桥后就不可能再回来,

    那么我们可以优先让速度慢的过河,因为其不可能返回,先过后过等效。

    如此一来,就可以得到上述的贪心策略。
    .
    .
    .
    .
    .
    程序:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int main()
    {
    	int n,a[10000];
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	int i=n;
    	long long ans=0,x,y;
    	while (1)
    	{
    		if (i==2) ans+=a[2];
    		if (i==3) ans+=a[1]+a[2]+a[3];
    		if (i<=3) break;
    		x=2*a[2]+a[1]+a[i];
            y=a[1]+a[i]+a[1]+a[i-1]; 
            if (x<y) ans+=x; else ans+=y;
            i-=2;
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    剑指OFFER 滑动窗口的最大值
    剑指OFFER 正则表达式匹配
    linux动态链接库的使用
    剑指OFFER 序列化二叉树
    剑指OFFER 数字在排序数组中出现的次数
    剑指OFFER 数组中的逆序对
    剑指OFFER 反转链表
    剑指OFFER 二叉树的深度
    剑指OFFER 矩形覆盖
    网络相关的命令工具-iptables
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/10292828.html
Copyright © 2011-2022 走看看