计蒜客 买书(dfs搜索)

计蒜客 买书

#include <bits/stdc++.h>

using namespace std;
const int max_n = 35;
int val[max_n];
int used[max_n];
int m, n, k;
bool ok = false;

void dfs(int sum, int num, int idx) {
    if(sum == m && num == k) {//刚好满足条件
        ok = true;
        return;
    }

    for(int i = idx; i >= 0; --i) {
        if(!used[i] && sum + val[i] <= m && num + 1 <= k ) {
            used[i] = 1;
            sum += val[i];
            num++;

            dfs(sum, num, i-1);

            used[i] = 0;
            sum -= val[i];
            num--;
        }
    }
}


int main() {
    //freopen("data.in", "r", stdin);
    memset(used, 0, sizeof(used));
    memset(val, 0, sizeof(val));

    scanf("%d %d %d", &m, &n, &k);
    for(int i = 0; i < n; ++i) {
        scanf("%d", &val[i]);
    }

    sort(val, val+n);//从小到大排列
    dfs(0, 0, n-1);

    if(ok)
        printf("Yes\n");
    else
        printf("No\n");

    return 0;
}

### 使用DFS实现全排列算法 深度优先搜索(Depth First Search,简称DFS)是一种常用的遍历或搜索树或图的算法[^3]。在生成全排列的过程中,可以通过递归的方式模拟一棵多叉树的结构,在这棵树中,每一条从根节点到叶节点的路径代表了一个可能的排列组合。 以下是基于DFS实现全排列的具体方法: #### 实现思路 1. 定义一个数组`a[]`存储待排列的元素。 2. 设定初始状态为未排列任何元素的状态。 3. 通过递归调用`dfs()`函数逐步填充每一位上的数字。 4. 在每一层递归中,尝试将当前位置与后续位置的所有元素进行交换,并进入下一层递归处理剩余部分。 5. 当到达最后一层时,表示已找到一种完整的排列方案并输出该结果。 6. 返回上一层之前恢复原状以便探索其他可能性。 下面给出一段C++代码作为示例来展示这一过程: ```cpp #include <iostream> using namespace std; // 深度优先搜索函数,用于生成排列 void dfs(int a[], bool used[], int depth, int n, int path[]) { if (depth == n) { // 如果已经填满n个数,则打印当前排列 for (int i = 0; i < n; ++i) { cout << path[i]; if (i != n - 1) cout << ' '; } cout << endl; return; } for (int i = 0; i < n; ++i) { // 尝试放置每个尚未使用的数 if (!used[i]) { // 若此数还未被使用 path[depth] = a[i]; // 放置这个数 used[i] = true; // 标记为已使用 dfs(a, used, depth + 1, n, path); // 继续解决下一个位置 used[i] = false; // 回溯:取消标记 } } } int main() { const int N = 3; int a[N] = {1, 2, 3}; bool used[N] = {false}; int path[N]; dfs(a, used, 0, N, path); return 0; } ``` 上述程序定义了两个辅助数组——`path[]`用来保存当前正在构建的部分解;而布尔型数组`used[]`则记录哪些元素已经被选取过了。每当成功完成一次完整的选择序列之后就会立即输出它们[^4]。 #### 时间复杂度分析 由于需要枚举所有的排列情况,因此总的运行时间为O(n!)级别,其中n表示输入数据规模大小即要参与排列的对象数目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值