递归再理解

就简单的背包问题举例:
设有一个背包可以放入的物品重量为S,现有n件物品,重量分别为w1,w2,.. .,wn。问能否从这n件物品中选择若干件放入此背包,使得放入的重量之和正好为S。如果存在一种符合上述要求的选择,则称此背包问题有解,否则此问题无解,试用递归方法设计此背包问题的算法。


用递归思想解决问题,要学会把大问题化为小问题,把看似一个整体的问题细化到其中的一部,进行思考。并且要学会用“撒手”观念去解决问题。

这里写图片描述
例如背包问题的解决,首先拿到问题思考,把这个大的问题化为单个物品的小问题,则对于单个物品来说就有两种情况,一是装进背包,二是不装进背包,这样就好考虑了。
这里写图片描述
如图所示,递归的出口是当S=0,或者S<0,或者S>0且n<1;

int knapsack(int S,int n)
{    if(S==0) return 1;
     else  if(S<0||(S>0&&n<1))  return 0;
     else 
     {  if(knapsack(S-W[n],n-1))
         {   cout<<W[n]; return 1;  }
         return(knapsack(S,n-1));
      }
} 

这是代码,只不过N是从最大值开始的,需要不断的减。
其中的:

if(knapsack(S-W[n],n-1))
         {   cout<<W[n]; return 1;  }
         return(knapsack(S,n-1));

则是对递归的实现,

if(knapsack(S-W[n],n-1))
         {   cout<<W[n]; return 1;  }

如果当前的物品放进去了,会出来一个结果,如果不成功,则不放进去,进行下一次的选择。此时就用到了“撒手”的观念,我不管以后的操作,knapsack(S-W[n],n-1)就是能够判断当装进这一个物品是否会成功装满。
如果最后不成功则此时就会选择不装进去。


续更:
看完了我的有关递归的文章,是否对一个新的递归可以自己独立的分析出来,或者自己拿到一个题,可以自己设计出一个递归来。
快速幂的递归实现:

LL S=1;
LL di_pow(LL a,LL b){
   if(b==0) return 1;
   S=di_pow(a*a,b>>1);
   if(b&1) S*=a;
    return S;
}

这段代码是否能够看懂?
在函数体中,函数的实参的作用域和作用时间需要我们好好的研究一下。
在此递归函数中,S=di_pow(a*a,b>>1); 这是子问题的生成段。
生成的子问题是:
从上到下分析这个问题,最开始是最大的次方,从这开始,开始转换为比它小的且满足b的对应二进制位的运算。比如:3的22次方。 22次方拆分成 16 4 2;转换成二进制是10110.当b右移一位时,a*a; 因为是传参函数,所以作用域是整个函数体,而这是递归,有其独特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值