Bridge UVA - 10037

题目链接:传送门

思路:大致题意就是n个人过桥时间有快慢,每次只能两个人过,n个人中只有一个手电筒,每次都得拿着手电筒才能过桥,意思就是两个人过去之后,还要回来送手电筒,让我们找一种策略让所有人最短时间内通过,输出最短时间以及过得的策略。

t时间,每个人过桥的时间由小到大排序

  • n=1时,直接过去,t=a[0]
  • n=2时,直接过去,t=max(a[0],a[1]),也就是t=a[1]
  • n=3时,假设ABC三人策略1:AC,A,AB和AB,A,AC,两种策略所用时间相同t=a[0]+a[1]+a[2]
  • n>=4时,假设a[0~n-1](下标从0到n-1共n个人)

        一种策略:a[0]和a[n-1]过桥,a[0]回来送手电筒,a[0]和a[n-2]过桥,a[0]回来,至此没过去的还有a[0],a[1].....a[n-3],

        然后n-=2(因为已经过去了最后两个人,还剩n-2人),循环一直让最快的(a[0])把最后的两个人送过去,再回来,直到n<4

        另一种策略:让a[0]和a[1]先过去,a[0]回来,再让a[n-1]和a[n-2]过去,a[1]回来(过去的最小的回来),n-=2,循环,直到n<4

代码实现:主要说明循环里如何操作(因为这个有点难想想)

		while(n>=4){
			if(a[n-1]+2*a[0]+a[n-2]>=a[n-1]+2*a[1]+a[0])
			{
				//ans+=a[n-1]+2*a[1]+a[0];
				cout<<a[0]<<" "<<a[1]<<endl<<a[0]<<endl<<a[n-2]<<" "<<a[n-1]<<endl<<a[1]<<endl;
			}else{
				//ans+=a[n-1]+2*a[0]+a[n-2];
				cout<<a[0]<<" "<<a[n-1]<<endl<<a[0]<<endl<<a[0]<<" "<<a[n-2]<<endl<<a[0]<<endl;
			}
			n-=2;
		}

以上就是解决人数超过4人的两种选择方案:a[n-1]+2*a[0]+a[n-2]>=a[n-1]+2*a[1]+a[0]

我们把n个人先抽出前两个和最后两个AB,YZ,策略1是AB,A,YZ,B或者策略2是AZ,A,AY,A

即:策略1所需时间a[n-1]+2*a[1]+a[0],策略2所需时间:a[n-1]+2*a[0]+a[n-2]

其目的就是把最后两个人送到桥那边,这边还有A,B和剩下的n-4个人,那么进行循环的条件就是继续把桥这边的最后两个人送过去,知到n<4,所以策略1和策略2相比较我们只选择最优解即可

code :ac代码

#include<iostream>
#include<algorithm>
using namespace std;
int a[1005];
int f(int n){//递归实现总时间的输出 
	if(n==1)return a[0];
	else if(n==2)return a[1];
	else if(n==3)return a[0]+a[1]+a[2];
	else
	{
		if(a[n-1]+2*a[0]+a[n-2]>=a[n-1]+2*a[1]+a[0])
		return a[n-1]+2*a[1]+a[0]+f(n-2);
		else
		return a[n-1]+2*a[0]+a[n-2]+f(n-2);
	}
}
int main()
{
	int t,n,flag=0;//flag换行的作用 
	cin>>t;
	while(t--){
		if(flag)cout<<endl;//第一个组测试数据不换行,之后每组换行 
		cin>>n;
		for(int i=0;i<n;i++)
		cin>>a[i];
		sort(a,a+n);
		cout<<f(n)<<endl;
		while(n>=4){
			if(a[n-1]+2*a[0]+a[n-2]>=a[n-1]+2*a[1]+a[0])
			{
				//ans+=a[n-1]+2*a[1]+a[0];
				cout<<a[0]<<" "<<a[1]<<endl<<a[0]<<endl<<a[n-2]<<" "<<a[n-1]<<endl<<a[1]<<endl;
			}else{
				//ans+=a[n-1]+2*a[0]+a[n-2];
				cout<<a[0]<<" "<<a[n-1]<<endl<<a[0]<<endl<<a[0]<<" "<<a[n-2]<<endl<<a[0]<<endl;
			}
			n-=2;
		}
		if(n==3){
			cout<<a[0]<<" "<<a[1]<<endl<<a[0]<<endl<<a[0]<<" "<<a[2]<<endl;
		}
		if(n==2)
		cout<<a[0]<<" "<<a[1]<<endl;
		if(n==1)
		cout<<a[0]<<endl;
		flag=1;
	}
	return 0;
 } 

   总结:以上到这基本上就完了,最后注意一下换行的输出(第一组数组不换行,其后每组数据都换行)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值