c语言刷题洛谷P1036 [NOIP2002 普及组] 选数(深度优先算法搜索)

看题目戳这里:[NOIP2002 普及组] 选数 - 洛谷

可以先做完再来看博客哦!


目录

一:题目分析:

二:解题

1.判断质数的函数:

2.深度优先算法求解组合数目:

3.求出k个数的全排列:

三:完整代码


一:题目分析:

题目描述

已知 n个整数 x1,x2,⋯ ,xn以及 1 个整数 k(k

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​≤5×10^6)    (int型就可以了)

输出格式

输出一个整数,表示种类数。


二:解题

1.判断质数的函数:

这里用最暴力的方法:(如果你牛逼可以用别的,质数筛等等)


int sushu(int x)//判断质数的函数
{
    if (x == 2 || x == 3 || x == 5)
        return 1;
    if (x < 2 || x % 2 == 0)
        return 0;
    for (int i = 3; i < sqrt(x); i += 2)//每次加2提高效率,虽然复杂度一样^_^
        if (x % i == 0)
            return 0;
    return 1;
}

2.深度优先算法求解组合数目:

首先要创建数组来存储数据和作为标记数组(定义的是全局变量更方便一点)


int count;//记录组合的个数
int arr[20];//存储数据
int book[20];//标记数组

然后就是实现函数:


void dfs1(int x, int num)//深度优先算出有几种可能,这个数量是答案乘以k个数全排列的个数
{
    if (x == 0)//如果到了k这么多层,这里的x就会等于0,然后进行质数判断
    {
        if (sushu(num))
            count++;
        return;//不管是不是质数到了k层都要退出
    }
    for (int i = 0; i < n; i++)
    {
        if (book[i] == 0)//如果那个数没有用
        {
            book[i] = 1;//标记用了
            dfs1(x - 1, num + arr[i]);//进入下一层
            book[i] = 0;//出来以后一定要记得把标记变回来
        }
    }
    return;
}

3.求出k个数的全排列:

由上面可知dfs1算出来的是答案个数乘以k的全排列,因为这样算的话只要加数的位置交换就又算作一种情况:

c语言刷题洛谷P1036 [NOIP2002 普及组] 选数(深度优先算法搜索)_第1张图片

 所以要求出k个数的全排列:

void dfs2(int x)//求出k个数的全排列的个数
{
    if (x == 0)//结束递归条件
    {
        num++;
        return;
    }
    for (int i = 0; i < k; i++)
    {
        if (book2[i] == 0)//如果没有用
        {
            book2[i] = 1;//标记已用
            dfs2(x - 1);
            book2[i] = 0;//标记还原
        }
    }
    return;
}

最后count/=num就是最终答案。

三:完整代码


#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
int count;
int num;
int arr[20];
int book[20];//标记数组
int book2[20];//标记数组
int n, k;
int sushu(int x)//判断质数的函数
{
    if (x == 2 || x == 3 || x == 5)
        return 1;
    if (x < 2 || x % 2 == 0)
        return 0;
    for (int i = 3; i < sqrt(x); i += 2)
        if (x % i == 0)
            return 0;
    return 1;
}
void dfs1(int k, int num)//深度优先算出有几种可能,这个数量是答案乘以k个数全排列的个数
{
    if (k == 0)
    {
        if (sushu(num))
            count++;
        return;
    }
    for (int i = 0; i < n; i++)
    {
        if (book[i] == 0)//如果没有用
        {
            book[i] = 1;//标记用了
            dfs1(k - 1, num + arr[i]);//进入下一层
            book[i] = 0;//出来以后一定要记得把标记变回来
        }
    }
    return;
}
void dfs2(int x)//求出k个数的全排列的个数
{
    if (x == 0)//结束递归条件
    {
        num++;
        return;
    }
    for (int i = 0; i < k; i++)
    {
        if (book2[i] == 0)//如果没有用
        {
            book2[i] = 1;//标记已用
            dfs2(x - 1);
            book2[i] = 0;//标记还原
        }
    }
    return;
}
int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++)
        scanf("%d", arr + i);
    dfs1(k, 0);
    dfs2(k);
    count /= num;
    printf("%d", count);
}

最后,如果你觉得这篇博客对你有所帮助的话,不妨点点赞,收收藏,转转发,你们的支持就是我前进的动力(一个赞一道题)!!!!

你可能感兴趣的:(c语言,数据结构,算法,深度优先)