第三周作业-A

题目描述:
Given n positive numbers, ZJM can select exactly K of them that sums to S. Now ZJM wonders how many ways to get it!
输入:
The first line, an integer T<=100, indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate n, K and S. The second line, n integers indicate the positive numbers.
输出:
For each case, an integer indicate the answer in a independent line.
example:
Input
1
10 3 10
1 2 3 4 5 6 7 8 9 10
Output
4
提示:
Remember that k<=n<=16 and all numbers can be stored in 32-bit integer
题目思路:
对于选数问题,我们想到的操作就是dfs,在dfs过程中我们可以选择一个数然后往下深入,对于每个数可以选择和不选择,这样就可以列举所有的情况,为2^n种,但是这个题没有必要列举所有的情况,在这里我们称之为剪枝。
首先,如果选择的个数超过了k个,那么就不用再选择了,而是判断他们的和是不是s,其次,如果和是s的话就方法数目++,不是的话应该倒回到起始状态重新选择。
还要注意本题输出的是方法的个数,而且是多次操作,所以记录可行的方法的个数的时候不能单独用一个全局变量,而是在dfs内部统计好操作次数之后返回到main里面赋值给对应的变量。那么我们设计的时候就要先遍历把每个变量都选一遍试试,如果到了选择的个数就比较和是不是s,是的话就返回1,而对于num来说返回1就是方法个数+1,返回0就是不变,所有操作完成之后就可以返回操作的方法数了。

int dfs(int n,int sum,int start,int end)
{
	if(n==0)
	{
		if(sum==s)
		return true;
		else
		return false;
	}
	int num=0;
	for(int i=start;i<=end;i++)
	{
		num=num+dfs(n-1,sum+a[i],i+1,end);
	}
	return num;
}

同时也要注意这个变量每次要清零,否则会错误。

int num=0;

代码如下:

#include<iostream>
using namespace std;
int a[1000000];
int n,k,s;
int dfs(int n,int sum,int start,int end)
{//n为剩余选择的个数,初始就是题目中的k,sum为递归过程中的和,最后要和s比较,start和end就是选择的开始与结束,那么本题就是开始的位置依次往后,然后每个开始的位置都for一遍选择
	if(n==0)
	{
		if(sum==s)
		return true;
		else
		return false;
	}
	int num=0;
	for(int i=start;i<=end;i++)
	{
		num=num+dfs(n-1,sum+a[i],i+1,end);//这里可以记录方法的个数,就在于前面返回值是1还是0,返回1的话救赎num+=1,返回0就不变
	}
	return num;
}
int main()
{
	int t;
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		int num=0; 
    	cin>>n>>k>>s;
    	for(int j=0;j<n;j++)
    	{
    		cin>>a[j];
		}
		num=dfs(k,0,0,n-1);
		cout<<num<<endl;
	}
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值