Codeup4.3-问题 C: 神奇的口袋

题目:
	有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。
John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,
那么利用这个神奇的口袋,John就可以得到这些物品。

问题:
	John有多少种不同的选择物品的方式。

输入:
	输入的第一行是正整数n (1 <= n <= 20),表示不同的物品的数目。接下来的n行,每行有一个1到40之间的正整数,
分别给出a1,a2……an的值。

输出:
	输出不同的选择物品的方式的数目。

样例输入:
2
12
28
3
21
10
5

样例输出:
1
0
总结:

此题属于递归问题,关键是找递归边界与递归式。

/*
	Author:Jian
	Language:C/C++
	Environment:Visual Studio 2012
*/

#include<iostream>
#include<cstdio>

using namespace std;

//num:保存物品的体积
int num[25] = {0};

//递归用的函数
int Func(int n, int sum){
	
	if(sum<0) return 0;
	if(sum==0) return 1;
	if(n==0) return num[0] == sum ? 1:0;
	else return Func(n-1,sum)+Func(n-1,sum-num[n]);

}

int main(){
	
	//n:保存物品的数目 1<=n<=20
	int n=0;

	//由于可能有多组输入所以循环条件当作判断
	//若输入ctrl+z表明退出循环(当输入ctrl+z时候scanf()会返回-1)(EOF值正好为-1)
	while(scanf("%d",&n)!=EOF){

		//循环输入n个物品的体积
		for(int i=0;i<n;i++){
			scanf("%d",&num[i]);
		}

		//输出不同的选择物品的方式的数目
		printf("%d\n",Func(n-1,40));

	}

	system("pause");
	return 0;
}
	可能有的小伙伴会对Func(n-1,40)以及递归式Func(n-1,sum)+Func(n-1,sum-num[n])感到疑惑,我们不妨举个例子来深入了解。
假设n=3,此时输入了三个物品的体积:20,20,20。此时num[0]=num[1]=num[2];
根据递归算法过程如下所示:
Func(2,40)->Func(1,40)+Func(1,20)->1+2=3
Func(1,40)->Func(0,40)+Func(0,20)->0+1=1
Func(1,20)->Func(0,20)+Func(0,0)->1+1=2
Func(0,40)->return 0
Func(0,20)->return 1
Func(0,0)->return 1
	首先我们明确一点,我们要得到的是不同的选择物品的方式的数目,所以递归函数返回值应该是记录不同的选择方式数。
我们不难发现当输入f(2,40)时候实际上是从数组num最后一个位置(因为此时仅有三个数据输入)从前进行递归遍历。注意递归函数里一直采
取两种策略,“选择策略”Func(n-1,sum-num[n])与“不选择策略”Func(n-1,sum)。
我们注意到当使用选择策略时,相应的剩余体积(sum)-此时遍历的物品的体积(num[n]),不选择策略则保留当前剩余体积(sum)依次往前
遍历。其遍历类似于树的深度遍历,自顶向下以不同的方式依次遍历到首元素num[0]。(可以想象为一棵树)

	最后谈谈递归出口:当遍历到首位数组元素时,有三种情况,
1.若此时剩余体积已经为负值,表明该种选择方式已经超出题目要求体积必须为40。
2.若此时剩余体积恰好为0,则表明此前的遍历存在能满足体积必须为40的情况。
3.若此时遍历到首元素且剩余体积大于0,则说明此前的选择方案还未能满足体积为40的要求,则需要进一步判别,若其体积值首元素
num[0]恰好等于剩余体积(sum)则表明,其刚好满足题目要求40体积情况,否则不满足范围0。
4.若此时未遍历到首元素,则以两种策略进行遍历。

总结:实际上递归以两种策略进行,选择&不选择。其中选择策略里可能包含着超出题目要求的选择策略,也可能包含着满足题目要求的选择策略,不选择策略也是如此。但是我们关注的并不是选择策略,而是这种策略满不满足题目要求,所以当这种策略满足题目要求时,返回1,不满足返回0。归结一句话,每种策略其实可能视为从树的根到叶子结点的一条路径,满足返回1,不满足返回0。

题源:Codeup4.3-问题 C: 神奇的口袋
链接:http://codeup.cn/problem.php?cid=100000583&pid=2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值