[Luogu ブラシの質問] Blue Bridge Cup トピックのブレークスルー - 深さ優先検索 - dfs (1)

目次

前に書かれています:

トピック: P1036 [NOIP2002 普及グループ] 選択された数字 - Luogu | コンピュータ サイエンス教育の新しいエコロジー (luogu.com.cn)

タイトル説明:

入力形式:

出力フォーマット:

入力サンプル:

出力例:

問題解決のアイデア:

コード:

交流 !!!!!!!!!!

最後に書く:


前に書かれています:

どうすればアルゴリズムをうまく学習できますか?

個人的には質問の体系的なブラッシングが特に重要だと思いますが、

そのため、深さ優先探索を上手に学ぶために、暴力的な探索を使ってブルーブリッジカップに対処するために、

さっそくクイズを始めましょう!

トピック: P1036 [NOIP2002 普及グループ] 選択された数字 - Luogu | コンピュータ サイエンス教育の新しいエコロジー (luogu.com.cn)

タイトル説明:

入力形式:

最初の行には、スペースで区切られた 2 つの整数 n 、 k (1 ≤ n ≤ 20、k < n) が含まれます。

2 行目には、x1 、x2 、⋯、xn (1 ≤ 5 × 1061 ≤ xi ≤ 5 × 106) である n 個の整数が含まれます。

出力フォーマット:

種の数を表す整数を出力します。

入力サンプル:

4 3
3 7 12 19

出力例:

1

問題解決のアイデア:

深さ優先探索を使うと、

最初の注意点は、検索の順序です。

確認したいので、

私たちが書いた再帰構造は、すべてのケースをトラバースできます。

検索を初めて学ぶとき、再帰的な検索ツリーの観測を描画する必要があります。

再帰は非常に抽象的で、絵を描くことで問題を解決することができます。(上記の再帰的検索の基本的な考え方に慣れておくことは常に良いことです)

次は具体的なアイデア です

この問題は、n 個の数から k 個の数を選択し、それらを足し合わせて、それらが素数になるかどうかを判断することを求めています。

次に、n の数を入力する必要があります。

次に、最初に再帰的な検索ツリーを描画しましょう。

ルートノード: (入力 n=4、k=3、入力データ: 3,7,12,19)

各場所に配置できるデータのアイデア

下に再帰的に検索します。

 次に、トピックの要件に従って、

再帰的に検索を続けると、いくつかの組み合わせが違法であり、整理する必要があることがわかります。

再帰的に検索を続けます。

 

最終的には、4 つの組み合わせのみが有効であり、

次に、これら 4 つの組み合わせの合計が素数になるかどうかを判断します。

 次に剪定についてです。

場所にすでに格納されている数 + 残りのオプションの数 < 必要な数の場合、 prune .

コードの実装は次のとおりです。

コード:

//养成好习惯,包上常用头文件
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

//根据题目要求开数组
const int N = 30;

//arr数组用来读入数据
int arr[N];

//st数组用来存放数据
int st[N];

int n, k;

//记录素数个数并返回
int res = 0;

//判断是否是素数
bool is_prime(int sum)
{
    if(sum < 2)
    {
        return false;
    }
    for(int i = 2; i <= sum / i; i++)
    {
        if(sum % i == 0)
        {
            return false;
        }
    }
    return true;
}

void dfs(int u, int start)
{
    //如果:(已经存放的数 + 剩余可选的数 < 需要的数量)就剪枝
    if((u - 1) + (n - start + 1) < k)
    {
        return;
    }
    
    if(u > k)
    {
        //求和
        int sum = 0;
        for(int i = 1; i <= k; i++)
        {
            sum += st[i];
        }
        
        //判断
        if(is_prime(sum))
        {
            res++;
        }
        return;
    }
    
    for(int i = start; i <= n; i++)
    {
        st[u] = arr[i];
        dfs(u + 1, i + 1);
        st[i] = 0;
    }
}

int main()
{
    scanf("%d %d", &n, &k);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &arr[i]);
    }
    dfs(1, 1);
    printf("%d\n", res);
    return 0;
}

交流 !!!!!!!!!!

最後に書く:

以上がこの記事の内容です、お読みいただきありがとうございます。

この記事が気に入ったら、いいねとコメントをお願いします。また、ご意見をお書きください。

私と一緒にプログラミングを学びたい場合は、私に従ってください。私たちは一緒に学び、成長します。

今後もより質の高いコンテンツを出力していきますので、よろしくお願いします。

おすすめ

転載: blog.csdn.net/Locky136/article/details/129487461