信息学奥赛一本通(1232:Crossing River)

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;
}

http://ybt.ssoier.cn:8088/problem_show.php?pid=1232

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值