UVA-10037 Bridge 模拟+dfs

18 篇文章 0 订阅
11 篇文章 0 订阅

题意:有n个人要过桥,而他们手中只有一个电筒,而过桥的人数最多不超过两个,过桥必须有电筒,每个人过桥的时间不一样,过桥的时间取决于最慢的人,问:让所有人都过桥所花费最小的时间。

分析:先没想到用dfs就可以做,还是分析问题不过全面,先分析是已经很明显的是:让一个花时间最小的人,:和后面人过桥,时间可能会很小,但是有另一种方法:先花时间少的两个人过去,再让最小的过来,再后面的人去两个,让最次小的过来,也可以行的通。以为自己没有找到正确的方法,想好久。看了别人的才知道这两种方法都有可能,用dfs搜依次就可以求出所有答案了。唉,dfs真让人摸不着头脑啊;

先排序:.

1.如果只有1个人,直接就过去,t=a1;

2.如果两个人,一起过去,t=a2;

3.如果三个人,让最小的和后面的人依次过去,t=a1+a2+a3;

4.(麻烦点).假设有a1,a2,a[x-1],a[x].这里的中间的就可以不管了。

 方案1:t1=a2+a1+a[x]+a1+a[x-1] (让花时间最小的人和后面人依次过去,顺序无关)。

方案2:  t2=a2+a1+a[x]+a2+a2(让最小的两个人先过去,然后最小过来,再让后面最大的两个过去,再让第二个小的过来)

方案选择:t1-t2=a1+a[x]-2*a2>0?

先用递归求出时间,再递归打印路线就行了!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std ;

int a[1005];

int Get_time(int x)
{
	if(x==1) return a[0];
	if(x==2) return a[1];
	if(x==3) return a[0]+a[1]+a[2];
	if(2*a[1]<a[0]+a[x-2])
	  return a[0]+2*a[1]+a[x-1]+Get_time(x-2);
	else return 2*a[0]+a[x-1]+a[x-2]+Get_time(x-2);
}

void Get_way(int x)
{
	if(x==1){
		printf("%d\n",a[0]);
		return;
	}
    if(x==2){
		printf("%d %d\n",a[0],a[1]);
		return;
	}
   if(x==3){
		printf("%d %d\n%d\n",a[0],a[2],a[0]);
		printf("%d %d\n",a[0],a[1]);
		return;
	}
	if(x>3){
		if(2*a[1]<a[0]+a[x-2]){
		 printf("%d %d\n%d\n",a[0],a[1],a[0]);
		 printf("%d %d\n%d\n",a[x-2],a[x-1],a[1]);
	   }
	   else{
		    printf("%d %d\n%d\n",a[0],a[x-1],a[0]);
	    	printf("%d %d\n%d\n",a[0],a[x-2],a[0]);
	    }
	}
	Get_way(x-2);
}

int main()
{
	int t,n;
    scanf("%d",&t);
    while(t--){
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
		}
		sort(a,a+n);
		printf("%d\n",Get_time(n));
		Get_way(n);
		if(t)puts("");
    }
 	return 0 ;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值