Week3--作业--A - 选数问题 [DFS]

题目描述

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.

样例输入

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

样例输出

4

思路

综述

这个题有两种思路:

第一种(暴力点的):

需要从n个数中选出K个,构成和为S;
自然可以枚举n的所有子集,依次判定是否满足题意;
复杂度:O(K*2^n)

第二种:

可以类似隐式图的做法;
只不过这里的每个点是K维的;
利用DFS进行搜索,外加剪枝;
(这里的搜索类似维度的增加,从点的维度是0开始搜索,每到一个点判断是否加入该维度,加加加,加到K维,外加剪枝的条件)

剪枝条件:

条件1:节点的个数多于K且和不等于S,退出;
条件2:节点的个数未小于K但是和已经大于S,退出;
满足以上任意一个条件即可;

过程

Step1:输入

数组a存储的是n个数
用STL中的list链表ans来存储结果(单单就解答这个题目而言,没有必要存储所有的结果)

		 a = new int[n];
		for (j = 0; j < n; j++)cin >> a[j];
		list<int> ans;
Step2:搜索

其中tot是全局变量,不用担心形参的释放问题;
退出的条件:
ans链表的个数等于K,并且和为S

	if (ans.size() == K && sum == 0) {
		tot++;
		return;
	} 

剪枝问题:
除了之前的两个外,加上了触碰到了a数组的外面,也就是搜索到n个数之外的。


	if (i >= n) return;
	if (sum < 0 || ans.size()> K) return;

每到一个点,两个方向,一是加上该点继续向下,另一个是不加上该点继续向下;

	solve(i + 1, sum, ans);
	ans.push_back(a[i]);
	solve(i + 1, sum -= a[i], ans);
	ans.pop_back();

总结

深入思考:
单单就这个题而言,没必要加上list;
可以在搜索的过程中,加上一个参数number(int)来记录当前的维度情况,也就是当前选择了多少点。
这样可以最大化的降低复杂度。

代码

#include <iostream>
#include <list>
using namespace std;
int tot = 0;
int K = 0;
int s;
int n;
int* a;
void solve(int i, int sum, list<int>& ans) {
//退出
	if (ans.size() == K && sum == 0) {
		tot++;
		return;
	} 
	//剪枝
	if (i >= n) return;
	if (sum < 0 || ans.size()> K) return;
	//不选
	solve(i + 1, sum, ans);
	ans.push_back(a[i]);
	//选
	solve(i + 1, sum -= a[i], ans);
	ans.pop_back();
}
int main() {
	
	int t, i,j;
	cin >> t;
	for (i = 0; i < t; i++) {
		cin >> n >> K >> s;
		 a = new int[n];
		for (j = 0; j < n; j++)cin >> a[j];
		list<int> ans;
		//开始搜索
		solve(0, s, ans);
		cout << tot << endl;
		tot = 0;
		delete[]a;
	}
}
发布了29 篇原创文章 · 获赞 14 · 访问量 1258

猜你喜欢

转载自blog.csdn.net/weixin_44552961/article/details/104984415