1232:Crossing River
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 6415 通过数: 2761
【题目描述】
几个人过河,每次过两人一人回,速度由慢者决定,问过河所需最短时间。
【输入】
输入t组数据,每组数据第1行输入n,第2行输入n个数,表示每个人过河的时间。
【输出】
输出t行数据,每行1个数,表示每组过河最少时间。
【输入样例】
1
4
1 2 5 10
【输出样例】
17
【分析】
过桥问题是贪心算法的经典问题,有很多种变化,笔试面试中也经常碰到。本题贪心思想就是能者多劳,很容易想到尽可能利用速度快的人,且尽可能先把慢的人送走。
首先,先将过河时间从小到大进行排序,也就是说快的人在前,慢的人在后。
一、当人数 ≤ 3 时:
只有 1 个人:过河时间为 a[1];
只有 2 个人:过河时间为 a[2];
只有 3 个人:过河时间为 a[1] + a[2] + a[3];
二、当人数 > 3 时:每次让最慢的两个人过河,有两种过河方案:
1、过河最快的是 a[1],次快的为 a[2],次慢的为 a[n-1],最慢的为 a[n];
2、方案1:a[1]和a[n-1]一起走,a[1]回,a[1]和a[n]一起走,a[1]回,完毕。时间:a[n-1]+a[1]+a[n]+a[1],即:2*a[1]+a[n-1]+a[n];
3、方案2:a[1]和a[2]一起走,a[1]回,a[n-1]和a[n]一起走,a[2]回,完毕。时间:a[2]+a[1]+a[n]+a[2],即:a[1]+2*a[2]+a[n];
4、每次对两种过河方案取最小值。
以样例为例:1 2 5 10过河,方案1: 1和10过河,1返回,1和5过河,1返回,1和2过河完毕。时间:10+1+5+1+2=19。方案2: 1和2过河,1返回,5和10过河,2返回,1和2过河完毕。时间:2+1+10+2+2=17。取19和17的最小值,结果17。
【参考代码】
#include <stdio.h>
#define N 1010
int a[N];
int min(int x,int y)
{
return x < y ? x : y;
}
int main()
{
int i,j,n,t,tmp,ans;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<n;i++)
{
for(j=i+1;j<=n;j++)
{
if(a[i]>a[j])
{
tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
}
ans=0;
while(n > 3)
{
ans+=min(a[1]*2+a[n]+a[n-1], a[2]*2+a[1]+a[n]);
n-=2;
}
if(n==1)
ans+=a[1];
else if(n==2)
ans+=a[2];
else
ans+=a[1]+a[2]+a[3];
printf("%d\n",ans);
}
return 0;
}