一本通 1232:Crossing River(贪心)

1232:Crossing River
【题目描述】
几个人过河,每次过两人一人回,速度由慢者决定,问过河所需最短时间。

【输入】
输入t组数据,每组数据第1行输入n,第2行输入n个数,表示每个人过河的时间。
【输出】
输出t行数据,每行1个数,表示每组过河最少时间。
【输入样例】
1
4
1 2 5 10

【输出样例】
17

个人思路:
一步步分解。
每组操作都将剩下的人中最慢和次慢的人(贪心)送过去。
操作中有两种方法:(都是想办法让剩下人中n和n-1过去)
第一种:最快的人1带动慢的n和n-1,这样运过n和n-1共需要A1+An+A(n-1)+A1时间。
第二种:最快的1先和次快的2过去,然后最快的1回来,让n和n-1一起过去,然后让刚开始去的2回来,时间为A2+A1+An+A2。
看一下这两种哪一种时间小,也就是说比较 A(n-1)+A1与2*A2的关系。
总之,每组操作之后,在岸对面留下的都是慢的人,因为不要让他们回来,所以回来的都是快的。
代码:

#include<iostream>
#include<string.h> 
#include<algorithm>
#include<stdio.h>
using namespace std;
//从过程入手考虑 
//有两种(都是想办法让n和n-1过去):第一种最快的人1带动慢的n和n-1,这样运过n和n-1共需要A1+An+A(n-1)+A1时间。
//第二种,最快的1先和次快的2过去,然后最快的1回来,让n和n-1一起过去,然后让刚开始去的2回来,时间为A2+A1+An+A2。
//看一下这两种哪一种时间,也就是说比较 A(n-1)+A1与2*A2的关系。 

//总之,每组操作之后,在岸对面留下的都是慢的人 
int main()
{
 int t;
 cin>>t;
 int a[10001];
 for(int i=1;i<=t;i++)//t个测试 
 {
  int n;
  cin>>n;
  memset(a,0,sizeof(a));
  for(int j=1;j<=n;j++)
   cin>>a[j];
  sort(a+1,a+1+n);//排序
  int sheng=n;//剩下的人 
  long long int sum=0;//总时间 
  while(sheng!=2&&sheng!=3)//分析一下结束的时候
  {
   sum+=min(2*a[2],a[sheng-1]+a[1])+a[1]+a[sheng];
   sheng=sheng-2;//每组操作运过剩下的最慢和次慢
   } 
  if(sheng==2)
   sum+=a[2];
  else if(sheng==3)//当只剩下3个的时候,只能选用第一种方法
   sum+=a[sheng]+a[sheng-1]+a[1]; 
  
  cout<<sum<<endl;  
 }
 
 
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值