分治递归之奶牛过河问题

问题描述:

every year the cows hold an event featuring a peculiar version of hopscotch that involves
carefully jumping from rock to rock in a river. The excitement takes place on a long, straight
river with a rock at the start and another rock at the end, L units away from the start (1 L
1, 000, 000, 000). Along the river between the starting and ending rocks, N (0 N 50, 000)
more rocks appear, each at an integral distance Di from the start (0 < Di < L).
To play the game, each cow in turn starts at the starting rock and tries to reach the finish
at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to
the final rock, ending up instead in the river.


Farmer John is proud of his cows and watches this event each year. But as time go es by, he
tires of watching the timid cows of the other farmers limp across the short distances b etween
ro cks placed to o closely togethe r. He plans to remove several ro cks in order to increase the
shortest distance a cow will have to jump to reach the end. He knows he cannot re move the
starting and ending ro cks, but he calculates that he has enough resources to remove up to M
ro cks (0 M N).
Farmer John wants to know exactly how much he can increase the shortest distance before he
starts removing the rocks. Help Farmer John determine the greatest possible shortest distance
a cow has to jump after removing the optimal set of M rocks. In other words, you need help
John to find a way to remove M blocks, so that in the rest of the blocks, the distance between
two adjacent blocks which have a minimum spacing is the largest

解题思路:
     因为每两个rock(r[i]和r[i+1])之间都会有一个距离,而这个距离可能会比其他的多个连续的两rock((r[i],r[i+1]),r[i+1],r[i+2])...r[i+m-2],r[i+m-1]))之间距离相加还要大。因此,我们考虑所有两个相邻rock(r[i]和r[i+1])之间的距离,并找出最大值max和最小值min。计算最大最小的中间值mid=(max+min)/2。对于任意连续的多个rock(r[j]...r[j+k-1],共计k个点),如果(r[j],r[j+k-1])之间的距离小于mid,则很明显这几个rock是一次可达的,因而中间的那些rock(r[j]...r[j+k-1],共计k个点)可以去掉。如果,k小于删除点的数量限制,那么我们可以依据二分法向上调大mid;相反,如果k大于删除点的数量限制,我们可以二分法调小mid。直到达到我们的要求。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
查找假币问题可以通过分治递归求解。 假设有n个硬币,其中有且仅有一个假币,重量比真币轻。现在给你一个天平,问最少需要称多少次,才能找出假币。 解题思路: 1.如果有1个硬币,显然不需要称。 2.如果有2个硬币,只需要称一次即可。 3.如果有3个硬币,可以将它们分成两组,分别称一次。如果两组的重量相等,那么假币在第三组中,需要再称一次;否则假币在较轻的那组中,需要再称一次。 4.如果有4个硬币,可以将它们分成两组,分别称一次。如果两组的重量相等,那么假币在另外两个硬币中,需要再称一次;否则假币在较轻的那组中,需要再称一次。 …… 可以发现,如果有n个硬币,可以将它们分成三组:每组都有n/3个硬币。然后分别称一次,如果三组的重量相等,那么假币在剩余的n-3n/3=n/3个硬币中,需要再称一次;否则假币在较轻的那组中,需要再称一次。这个过程可以用递归实现。 下面是C++代码实现: ``` #include<iostream> using namespace std; int weigh(int n) { if(n==1) return 0; //只有一个硬币,不需要称 if(n==2) return 1; //有两个硬币,只需要称一次 int w=weigh(n/3*2); //先将n个硬币分成三组,每组都有n/3个硬币 if((n-n/3*3)==1) return w+2; //剩余一个硬币,需要称两次 else if((n-n/3*3)==2) return w+1; //剩余两个硬币,需要称一次 else return w+2; //剩余三个硬币,需要称两次 } int main() { int n; cout<<"请输入硬币的个数:"; cin>>n; cout<<"最少需要称的次数为:"<<weigh(n)<<endl; return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值