选数问题(剪枝)

题意:

Given nn positive numbers, ZJM can select exactly KK of them that sums to SS. Now ZJM wonders how many ways to get it!

输入输出要求:

The first line, an integer T<=100T<=100, indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate nn, Kand S. The second line, nn integers indicate the positive numbers.

For each case, an integer indicate the answer in a independent line.

样例输入:

1
10 3 10
1 2 3 4 5 6 7 8 9 10

样例输出:

4

数据范围:
Remember that k<=n<=16k<=n<=16 and all numbers can be stored in 32-bit integer

思路:

整体思路:

可以枚举所有子集判断是否合法 ,复杂度O(𝐾·2^𝑛)

剪枝:

枚举的子集里面有很多显然不可能合法的情况,直接跳过这些情况:
1)选的数的个数超过了K
2)选的数的和超过了S

递归:

递归结束的条件是:if(res_size=K && sum=0)
在这里,我用sum定义还可以再加的数值

总结:

这是一个搜索问题,为了避免暴力搜索,剪枝及其重要!!

代码:

#include<iostream>
using namespace std;

int m,n,K,S;
int count=0;    //记录合法的组数
int res_size=0; 		//记录结果中数字个数 
int a[16];

void solve(int i,int sum,int *a)
{
	if(res_size==K&&sum==0)      //递归结束的条件
	{
		count++;
		return;	
	 }
	if(i>=n)	return;         //判断是否越界 
	if(res_size>K||sum<0) 	return;		//可行性判断
	
	solve(i+1,sum,a);				//不选
	res_size++;
	solve(i+1,sum-a[i],a);        //选
	res_size--; 
}

int main()
{
	cin>>m;
	while(m)
	{
		cin>>n>>K>>S;
		for(int i=0;i<n;i++)
			cin>>a[i];
		solve(0,S,a); 
		cout<<count<<endl;
		count=0;res_size=0;
		m--;	
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值