P1036——选数

题目描述:
已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29)。
输入输出格式
输入格式:

键盘输入,格式为:
n , k (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)

输出格式:

屏幕输出,格式为:
一个整数(满足条件的种数)。

输入输出样例

输入样例#1:

4 3
3 7 12 19

输出样例#1:

1

思路:
找到这些组合,显然是一个搜索问题。如果直接用DFS方法进行搜索,会导致出现组合重复排列的情况。所以每一次的搜索初始位置都比上一次加一。代码如下:

#include<iostream>
#include<cmath>
const int MAX = 30;
using namespace std;
int n, k;//数的总数和选取的数的总数
int _count = 0;//the total number of prime numbers
int sum = 0;//记录搜索时相加的和
int a[MAX];///记录数据
//a function of prime numbers
bool isPrime(int x) {
    if (x <= 1)
        return false;
    else if (2 == x)
        return true;
    else {
        for (int i = 2; i <= sqrt(x); i++)
            if (0 == x % i)
                return false;
    }
    return true;
}
//DFS搜索函数
/*这里我仔细讲解一下DFS,level表示的递归层数,在后面主函数调用时从零开始,starti表示搜搜索的初始位置。
我们先看递归窗口。若果starti>n-1且此时的层数还没有达到k,再往下搜索就越界了,所以我们return。但是如果在还没有越界的时候层数就达到k,那么我们就判断累加和sum是否为素数。是的话计数器加一。然后在return。
最后我们看一看主体部分。搜索,就要把每种组合都找出来。我们用循环,从starti到n,不断变换初始搜索位置。当starti是搜索的初始位置时,sum加上a[starti],然后继续递归搜索,递归层数加一,但要注意,为了防止重复,我们把初始搜索位置也加一,这样不需要用vis数组记录是否访问。
最后,要释放sum,也就是减去a[j]即可
*/
void DFS(int a[MAX], int level, int starti) {
    if (starti > n - 1 && level < k)
        return;
    if (level == k) {
        if (isPrime(sum))
            _count++;
        return;
    }
    for (int j = starti; j < n; j++) {
        sum += a[j];
        DFS(a, level + 1, j + 1);
        sum -= a[j];
    }
}
int main()
{
    cin >> n >> k;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    DFS(a, 0, 0);
    cout << _count;
    return 0;
}




发布了14 篇原创文章 · 获赞 3 · 访问量 157

猜你喜欢

转载自blog.csdn.net/IMDASHUAI/article/details/104422190