小孩过河时间问题

小朋友过桥问题:
 在一个夜黑风高的晚上,有n(n <= 50)个小朋友在桥的这边,现在他们需要过桥,但是由于桥很窄,每次只允许不大于两人通过,他们只有一个手电筒,所以每次过桥的两个人需要把手电筒带回来,i号小朋友过桥的时间为T[i],两个人过桥的总时间为二者中时间长者。问所有小朋友过桥的总时间最短是多少。

问题分析:

先将小朋友过河的时间从小到大排序

​​​​​​当一个小朋友过河时:时间sum=T[1];

当两个小朋友过河时:时间sum=T[2];

当三个小朋友过河时:时间sum=T[2]+T[1]+T[3]; 

/*

第一步小朋友1和小朋友2过河,时间为T[2];小朋友1回来,时间为T[1],小朋友1和小朋友3过河时间为T[3].

*/

当第四个小朋友过河时则会出现不同的情况:

一:小朋友1和小朋友2过河,时间为T[2];小朋友1回来,时间为T[1],小朋友1和小朋友3过河,时间为T[3];小朋友1回来,时间为T[1];小朋友1和小朋友4过河,时间为T[4]。

总时间为:2*T[1]+T[2]+T[3]+T[4];

二:小朋友1和小朋友2过河,时间为T[2];小朋友1回来,时间为T[1],小朋友3和小朋友4过河,时间为T[4],小朋友[2]回来,时间为T[2],再小朋友1和小朋友2过河时间为T[2]。

总时间为:T[1]+3*T[2]+T[4]

同理,当n个小朋友过河时也需要考虑这种情况:

/*

在这道题中我们可以用递归算法来思考,我在已经有n-2个小朋友过河的情况下,让小朋友1回来时,是让小朋友1继续带一个小朋友回去,还是让剩下的两个小朋友回去,再让小朋友2来接小朋友1呢?

*/

当n个小朋友过河时,设f(n-2)为前n-2个小朋友所花的时间

则第一种情况的时间为:f(n-2)+T[1]+T[n]+T[2]+T[2]

第二种情况的时间为:f(n-2)+T[1]+T[n-1]+T[1]+T[n]

如此我们只需要加入条件   当T[1]+T[n-1]>2*T[2]时进入第一种情况,反之则进入第二种情况

实现代码如下:

#include<stdio.h>

int AcrossRiver(int a[],int n); 

int main(){
	int n;
	scanf("%d",&n);
	int a[n+1];
	int num=0;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++){//时间排序,从小到大 
		for(int j=n;j>i;j--){
			if(a[i]>a[j]){
				num=a[j];
				a[j]=a[i];
				a[i]=num;
			} 
		} 
	}
	printf("%d",AcrossRiver(a,n));
	return 0;
}

int AcrossRiver(int a[],int n){
	if(n<=2){
		return a[n];
	}
	if(n==3){
		return a[2]+a[1]+a[3]; 
	}
	int f_n2 = a[2];
    int f_n1 = a[1]+a[2]+a[3];
    int f_n = 0;
    for(int i = 4; i <= n; ++i)
    {
    	if(a[1]+a[n-1]>=2*a[2]){
    		f_n = a[1] + 2*a[2] + a[i] + f_n2;
        	f_n2 = f_n1;
        	f_n1 = f_n;	
		}else{
			f_n=2*a[1]+a[n]+a[n-1]+f_n2;
			f_n2 = f_n1;
        	f_n1 = f_n;
		}
	}
	return f_n;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值