贪心算法—旅行者过河问题
Posted 云故里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心算法—旅行者过河问题相关的知识,希望对你有一定的参考价值。
N位旅行者来了河边。如果不借助船的话,大家是无论如何也不敢过河去的。不幸的是,N个人一共只有一条船,而这条船每次只能坐两个人。如果各自单独划船过河的话,N人所需要的时间已知;而如果两人同时过河,所需要的时间是这两个人各自单独过河所需时间中最慢的时间(比如两个人单独过河所需的时间分别是 2,3,那么如果他们一起过河,所需的时间就是3)。问题是,如何设计一个方案,让这N人尽快过河。
输入:
第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人单独过河所需要花时间。(0<Si<=100)
输出:
输出所有人都过河需要用的最少时间
样例输入:
1
4
1 2 5 10
样例输出:
17
首先,这道题很有意思对吧!,当然也很有难度,它是贪心算法的典型代表,什么?你不知道什么是贪心算法,…. 可以去百度一下,举个例子,让你从10个不一样大小的苹果中选择5个最大的,依次选一个,选5次,你会怎么选?当然每次都选剩下的苹果中最大的一个,对不对,嗯,没错,你每次都很贪心,都选最大的,这样,最终你选的5个苹果就是10个中最大的,好了,这就是贪心算法,实质是: 局部的最优解同时也满足全局的最优解
回到题中,求最少时间,分析一下,局部的最优解满不满足全局的最优解,当然满足,每个人过河的时间都最少,所有人花费的时间不就最少了,所以,你要每次都很贪心,每先把最浪费时间的两个人送走,可是怎么送呢? 注意只有一条船,船还是要有人开回来的,所有这就产生了两种方式,
注意,以下两种方式是针对4个人及以上的人数时考虑的方法,当人数为3时,只能用第一种方法,因为第二种方法要四个人才能完成,所以循环的条件为 n>2 (从0开始的,)
1. 让速度最快的那个人分两次将最费时间的两个人送走,然后它再把船开回来
最快的和最慢的过河,然后最快的将船划回来,再最快的和次慢的过河,然后最快的将船划回来.
即所需时间为:2*t[0]+t[n-2]+t[n-1]
2. 最快的和次快的合作,
最快的(即所用时间t[0])和次快的过河,然后最快的将船划回来,再次慢的和最慢的过河,然后次快的将船划回来.
即所需时间为:t[0]+2*t[1]+t[n-1]
每次都从上面的两种方式中选择时间最小的一种方式,当做送走 最费时间的两个人 所花费的时间,
下面以例子中的数据讲解一下:
1 2 5 10
初始n=4 ,
排完序后让 n=3
四个人对不对!! 满足循环条件 n>2,所以可以执行循环
1. 考虑第一种方法 t1=0
先让 1 和 10 过河 花费时间为 10 t1=10
1 把船划回来 花费时间为 1 t1=10+1=11
1 把船划回来 花费时间为 1 t1=16+1=17
此时 5 10都送走了,1 ,2和c船都在原处,对不对,
2.考虑第二种方法 t2=0
先让 1 2 过河 花费时间为 2 t2=2
1 划船回来 时间为 1 t2=2+1=3
5 10 划船过河 时间为 10 t2= 3+10=13
2 划船回来 时间为 2 t2=13+2=15
此时 5 10都送走了,1 ,2和c船都在原处,
两种方法尝试完毕,此时选择最少的时间 t2=15
此时n=1 ,河这边只剩下 1 2 当然,还有船
一起坐船走吧,时间为 2 所以总时间t= 15+2=17
int main()
{
int T,n,i,j,t,a[1001],res=0;
int c,min;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
/*冒泡排序*/
for(j=0;j<n-1;j++) /*进行9次循环 实现9趟比较*/
for(i=0;i<n-i-1;i++) /*在每一趟中进行9-j次比较*/
if(a[i]>a[i+1])
{
t=a[i];
a[i]=a[i+1];
a[i+1]=t;
}
--n;
while(n>2)
{
c=a[0]+a[1]*2+a[n]; //看解释 <1>
min=a[0]*2+a[n]+a[n-1]; //看解释 <2>
if(c<min)
min=c;
res+=min;//先把最长时间的两个人先送过去
n-=2;
}
if(n==0) /*只剩下一个人*/
res+=a[0];
else if(n==1) /*剩下两个人,时间按最大的那个人的算*/
res+=a[1];
else /*剩下三个人,最大的和最小的过去,最小的将船划回来,然后带着剩下的那个人过去*/
res+=a[0]+a[1]+a[2];
printf("%d\n",res);
}
return 0;
}
分析结束,如果还有什么更好的算法思想,可以在下方留言。
以上是关于贪心算法—旅行者过河问题的主要内容,如果未能解决你的问题,请参考以下文章