選數問題:給定n個數字,從中選擇k個使他們的和爲s,求有幾種組合方式。c++

選數問題

給定n個數字,從中選擇k個使他們的和爲s,求有幾種組合方式。
第一行會給一個T(T<=100),表示測試數據的組數,每一組中有兩行,第一行中有三個數字n,k,s;第二行給定n個數字。
將可能的組合方式數輸出。保證k<=n<=16,所有的數字範圍都在32位整數的表示範圍內。

sample input:
1
10 3 10
1 2 3 4 5 6 7 8 9 10

sample output:
4

思路:

  1. 由於題目給定了數字範圍不會太大,所以當然可以無腦暴力,寫個循環,每次保證第i個數被取到,再嵌套循環取i+1位置的數字,循環檢查是否能k個數字加起來等於s,若等於就count++;最後輸出count就可以。
  2. 可以使用遞歸的方式來解決,其實原理比較像深搜(一條樹的分支走到黑然後返回),需要判斷的就是他的結束條件,只有當k==0(可以用的數字用完了)並且sum == 0(恰好等於想得到的值)才說明這個選擇是對的,返回值1。
  3. 對於每一層遞歸,相當於是一個二叉樹,有兩個選擇方向:選擇當前數或者不選擇;對他們的結果求和就能返回答案。
  4. 對於判斷條件(begin>=length)一定要注意他放置的位置,需要在判斷完+1之後再判斷是否大於等於,如果需要選擇的數字在最後一位的話,將該判斷條件放到前面會導致
    組合方式缺少。或者可以寫兩個判斷條件,先判斷if(begin>length),在完成成功判斷後,再判斷一遍if(begin>=length)
  5. 由於這裏我們需要計算數組的長度,所以最好使用動態數組,如果自己創建數組的話需要注意,將數組傳入函數後,使用sizeof(a)來做是錯誤的,他會返回數組的大小*8,返回地址長度,所以比較建議使用vector,並用size()取數組長度。
#include <iostream>
#include <string>
#include <algorithm>
#include<cstdio>
#include<vector>

using namespace std;

ind(vector<int> a,int begin,int k,int sum)
{
	int length=a.size();

	if(k==0&&sum!=0)	return 0;//sum不對
	if(k==0&&sum==0)	return 1;
	if(begin>=length)	return 0;//這裏一定一定一定要在這裏,不能放在前面判斷;如果輸出的是最後一個數,需要在n+1位置上返回 
	return find(a,begin+1,k-1,sum-a[begin])+find(a,begin+1,k,sum);//向下檢索,選擇當前數或者不選擇
}
int main()
{
	int t=0;
	cin>>t;
	while(t--)
	{
		vector<int> arr;
		int n=0,k=0,s=0;
		cin>>n>>k>>s;
		for(int i=0;i<n;i++)
		{
			int temp=0;
			cin>>temp;
			arr.push_back(temp);
		}
		int ans=find(arr,0,k,s);
		cout<<ans<<endl;
	}
	return 0;
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章