目录
递归前言
粽所粥汁,计算n的阶乘,斐波那契数列,汉诺塔问题,和二叉树,背包问题等,都可谓是递归的应用,经典之经典!那什么(๑•̌.•̑๑)ˀ̣ˀ̣是递归呢?
看,这就叫递“龟”,这篇博客写完了,哈哈!
好了(ง •̀_•́)ง,不开玩笑了,说正经的,为了让大家更好的理解,博主给大家讲一个故事吧!希望大家认真听~
听懂了故事就弄懂了递归,从前有个小破站,站里有个新博主,新博主主动给大家讲故事,讲了什么故事呢?讲了从前有个小破站,站里有个新博主,新博主主动给大家讲故事,讲了什么故事呢?讲了从前~
大家看,这个故事有什么特点,他的特点是,在故事中再次提到相同的故事,这就是递归的核心理念了,回到编程领域,我们知道,一个函数是可以调用另一个函数的,作为特例,如果一个函数调用了自己,就像故事中提到了同样的故事
我们把函数在运行时,调用自己的情况,叫做递归! 也可以称之为有限“套娃”!
构成递归需具备的条件
1. 子问题须与原始问题为同样的事,且更为简单;
2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
注:其实递归是从递归入口一层一层,往下递归,直到遇到递归出口才一层一层的反弹,最终会反弹到调用处!现在用阶乘为例,带大家了解一下过程!
int f(int n)
{
if (n == 1)
return 1; //递归终止条件
else
return n * f(n - 1); //调用自己
}
这个递归在熟悉不过了,第2-3行是终止条件,第5行是调用自己。接下来我们就用n等于5的时候来画个图看一下递归究竟是怎么调用的 !
现在大家应该对递归有了一个初步的理解吧!(博主也是这几天在恶补,时间也很紧,就先写这么多吧)!接下来就开始题目解析咯!
题目
题目描述
设有一个背包可以放入的物品重量为S,现有n件物品,重量分别是w1,w2,w3,…,wn。问能否从这n件物品中选择若干件放入背包中,使得放入的重量之和正好为S。如果有满足条件的选择,则此背包有解,否则此背包问题无解。
输入
第一行为物品重量S(整数);
第二行为物品数量n,
第三行为n件物品的重量的序列。输出
有解就输出”yes!“,没有解就输出”no!“。
样例输入
20
5
1 3 5 7 9
样例输出
yes!
思路
我认为一个物品,只有会出现两种状态,一个就是放入背包,一个就是不放入,而递归的终止条件,也有两种状态,第一是背包剩余容量为0,第二就是背包剩余容量为负数,或者是物品放完了刚好。接下来博主会通过代码详细讲解,带大家进一步理解,这段话。
代码
#include <algorithm>
#include <iostream>
using namespace std;
int wi[10005];
int bag(int s, int n)//遍历所有组合
{
if (s == 0)
return 1;
else if (s < 0 || n == 0)
return 0;
else if (bag(s - wi[n], n - 1))//将a[n]放进背包
return 1;
else
return bag(s, n - 1);//不将a[n]放进背包
}
int main()
{
int n, i, s;
cin >> s >> n;
for (i = 1; i <= n; i++)
cin >> wi[i];
if (bag(s, n))
cout << "yes!";
else
cout << "no!";
return 0;
}
代码过程演示
20
5
1 3 5 7 9
a[1]=1;a[2]=3;a[3]=5;a[4]=7;a[5]=9;
首先是主函数中if(bag(20,5))
(1)bag(20,5)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//这一条语句的执行情况,要看bag(11,4)的情况
(2)bag(11,4)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//这一条语句的执行情况,要看bag(4,3)的情况
(3)bag(4,3)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//这一条语句的执行情况,要看bag(-1,2)的情况
(4)bag(-1,2)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//成立,返回bag(-1,2)=0;
//这时返回去看bag(4,3)的情况
(3)bag(4,3)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//因为bag(-1,2)=0,所以不成立,执行就下一条语句
return bag(s, n - 1);//现在此时bag(4,3)的取值 则取决于bag(4,2);
(5)bag(4,2)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//这一条语句的执行情况,要看bag(1,1)的情况
(6)bag(1,1)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//这一条语句的执行情况,要看bag(0,0)的情况
(7)bag(0,0)
if (s == 0) return 1;//成立,此时bag(0,0)=1
(6)bag(1,1)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//成立,此时bag(1,1)=1;
(5)bag(4,2)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//成立,此时bag(4,2)=1;
(4)bag(4,3)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//bag(-1,2)=0,不成立
return bag(4,2)//bag(4,3)=bag(4,2)=1
(3)bag(11,4)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//成立,此时bag(11,4)=1
(2)bag(20,5)
if (s == 0) return 1;//不成立,执行下一条语句
if (s < 0 || n == 0) return 0;//不成立,执行下一条语句
if (bag(s - wi[n], n - 1)) return 1;//成立,此时bag(20,5)=1
(1)if(bag(20,5))//成立,输出"yes!"
终于写完了,自己也清楚多了!加油!加油!加油!打败敌人吹气球~
看完了,别忘了,给博主点个关注哦!