这个问题的地址是:http://mitibar.com/superdrink.php
我只是解决了这个问题,并无入职那个公司的打算。
第一种是:遗传算法
我们还是模拟成数学问题:
我有一个有向图G,他有n个节点,其中任意一个节点a都有到另外n-1个节点的路径!每个路径上有一定的费用,我们要经过每个点,然后回到起点(起点是任意的),经过的点可以重复,并且要产生的费用最小。
如图三个节点的图:
这次,我们是运用贪心算法给出答案:
我们设函数f(n)为必须求出n个节点的路径。设函数g(n,m)是节点n到节点m的路径的大小,某种原料由机器n到机器m所转化所花的机器设备的钱。我们再设集合B(n,m)是{g(1,m),g(2,m),…,g(n,m)},他表示是节点1到节点n和节点m的所有路径的集合。设集合A(n,m)是{g(n,1),g(n,2),…,g(n,m)}的集合,他表示节点n和节点1到节点m的集合。设我们要寻找的路径为A路径,也就是花费最少的钱。
然后我们就可以回顾一下贪心算法的四个步骤:
1, 寻找最优子结构。
2, 递归描述最优子结构。
3, 证明递归式的正确性。
4, 写代码。
首先我们来看第一:寻找最优子结构
我们要寻找f(n)的A路径,首先,我们可以想到,要求n个节点的A路径,我们能不能求一个n-1节点的A路径呢?然后再求n-2的A路径,然后是n-3的A路径,以此类推,知道节点数剩下最后两个。求出这两个节点的A路径,我们就依次的先上走,直到求出了n个节点的A路径。
第二:递归描述最优子结构
根据我们上面的描述,我们可以这样求解我们的递归式:
f(n)=f(n-1)+ min (B(n-1,n))+ min (A(n,n-1))- (when X=Y)g(X,Y)
递归式有点复杂,不是吗?好了,我来解释一下,f函数和集合B前面是我们定义过的,那么min是从集合B中选出最小的值。简单点说,第一个min是选出的是n-1个节点到n最小的路径,第二个min是选出的是节点n到已知的n-1个节点的最小的路径,我们就是要找这两个路径。然后加上f(n-1)就是n个节点的路径了。好了,该解释什么是g(X,Y)了,我们设X代表从min (B(n-1,n))中选出的那个值得节点,而Y代表min(A(n,n-1))中选出的节点。我们必须减去这两个节点的路径。
但是我们不要忘了另外一种情况,就是X和Y相等时的节点,这时,我们回在计算A(n,n-1)的第二小的边,然后让他和Y加上g(n-1,n)比较大小,如果前者大,则选择后者,就是说我们还得加上g(X,Y)的大小,如果后者大,则选择前者。所以我在g(X,Y)前面加上了(when X=Y)。(在图中用红色表示如果选择完了,如下图,这说明由A到C和由C到A是相等的费用)
千万不要忘了结束递归的条件:
If n=2 return;
第三:证明递归式的正确性
这个说实话,也很好证明,我们采取数学归纳法,
当n=2时,递归式成立。
假设当n=k时成立。
我们让n=k+1,那么:
f(k+1)=f(k)+ min (B(k,k+1))+ min (A(k+1,k))- (when X=Y)g(X,Y)
因为f(k)是成立的,这是我们的假设,那么min (B(k,k+1))和min (A(k+1,k))会不会按照我们预期的工作呢?我想大家都已经知道了!
第四:写代码
剩下最不起眼的写代码了,这个留给大家吧!