题意:
给定n个正整数,从中挑出K个,使得这K个数的和为S,编程求出有多少种取数方案。
输入:
第一行给出一个正整数T(T<=100),表明有T组数据。接下来,每一组数据占两行,第一行给出题意中所述三个数n,K,S;第二行给出n个正整数。
Sample Input:
1
10 3 10
1 2 3 4 5 6 7 8 9 10
输出:
对每一组数据输出一个整数,表示方案个数,每组输出占一行。
Sample Output:
4
思路:
该问题要从n个数选出K个,并使其和为S,对于每个数都有选与不选两种情况,所以有2^n种情况,但枚举的复杂度过高,需对其中不合理的情况直接排除,如:和已经大于S,或者数的个数大于k。这些情况在选择过程中就可以排除。因此,使用递归的方法,依次对n个数进行选与不选的判断,对于递归过程中的不合理情况直接回到上一级,停止该递归支路,对于满足条件的情况,则计数变量+1,同时返回上一级,直到选择完所有数据。
出现的错误:
在结束前一组数据的选择后,未对保存n个数的容器进行清空,使得前一组数据影响下一组数据导致出现错误。
代码:
#include <iostream>
#include<vector>
using namespace std;
int N,M,SUM;
vector<int> val;
int count=0;
void select(int i,int thesum,vector<int>&arr)
{
if(arr.size()==M)
{
if(thesum==0)
count++;
return;
}
if(i>=N||thesum<0)
return;
select(i+1,thesum,arr);
arr.push_back(val[i]);
select(i+1,thesum-val[i],arr);
arr.pop_back();
}
int main(int argc, char** argv) {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
val.clear();
count=0;
vector<int> arr;
scanf("%d%d%d",&N,&M,&SUM);
for(int j=0;j<N;j++)
{
int temp;
scanf("%d",&temp);
val.push_back(temp);
}
select(0,SUM,arr);
if(i==0)
printf("%d",count);
else
printf("\n%d",count);
}
return 0;
}