【CSP考题扩展】暴力枚举(2)

2024-03-18 22:20
文章标签 csp 扩展 枚举 暴力 考题

本文主要是介绍【CSP考题扩展】暴力枚举(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【P1157 组合的输出】

题目链接

解题思路

  1. 主函数 (main): 读取两个整数 n n n r r r,分别代表总数和要组合的元素数。然后,它初始化两个向量 numsarrnums 用于存储从 1 到 n n n 的所有数字,而 arr 用于存储当前的组合,它的大小与 r r r 相等。

  2. 组合函数 (combine): 这是实现组合逻辑的函数。它接收四个参数:numsstartrarr

    • nums:包含所有可用数字的向量。
    • start:当前递归开始选择数字的起始位置。
    • r:还需要选择的数字数量。
    • arr:存储当前组合的向量。

    如果 r 等于 0,这意味着已经选择了足够的元素来形成一个组合,因此它将当前的组合 arr 打印出来。

    如果还需要选择元素(r 大于 0),函数将遍历从 startnums.size() - r 的数字(这样做是为了确保有足够的元素可以选择以填满剩余的位置),并对每个可能的数字执行以下操作:

    • 将该数字放入当前组合的相应位置。
    • 递归调用 combine 函数,更新起始位置和剩余需要选择的元素数。

完整代码

#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;void combine(vector<int>& nums, int start, int r, vector<int>& arr) {if (r == 0) {for (size_t i = 0; i < arr.size(); i++) {cout << setw(3) << arr[i]; }cout << endl;return;}for (int i = start; i <= nums.size() - r; i++) { // 修改循环条件,确保有足够的数字可以选择arr[arr.size() - r] = nums[i]; // 直接修改当前位置的元素combine(nums, i + 1, r - 1, arr); // 选择下一个数}
}int main() {int n, r;cin >> n >> r;vector<int> nums(n);vector<int> arr(r);for (int i = 1; i <= n; i++) {nums[i - 1] = i; }combine(nums, 0, r, arr);return 0;
}

【P1706 全排列问题】

题目链接

解题思路(1):

  1. 初始化排列: 首先,代码通过创建一个大小为n的向量perm来开始,这个向量被初始化为包含1到n的数字,这是因为我们需要生成从1到n的所有可能的排列。这个初始排列代表着最小的字典序排列。

  2. 打印初始排列: 在生成任何其他排列之前,初始排列(按字典序最小)首先被打印出来。这是通过printPermutation函数实现的,该函数遍历排列中的每个数字,并使用setw(5)来确保每个数字都有5个字符的宽度,这符合题目输出格式的要求。

  3. 生成和打印所有排列: 代码使用while循环和next_permutation函数来生成并打印所有可能的排列。在每次循环中,next_permutation都会将向量perm修改为下一个字典序更大的排列,直到所有排列都被生成。每次生成新排列后,都会使用printPermutation函数来打印它。

next_permutation函数详解:

  • next_permutation是C++标准库中的一个函数,用于重新排列范围内的元素到下一个字典序更大的排列。如果这样的排列存在,函数返回true;如果这是可能的排列中的最后一个(也就是没有字典序更大的排列),函数返回false
    • 工作原理next_permutation首先从范围的最后开始向前查找,直到找到一对连续的元素,其中前一个小于后一个。这对元素标记了需要重新排列的范围的边界。然后,函数再次从范围的末尾开始,寻找第一个大于前面找到的较小元素的元素,并与之交换。最后,函数逆置原先找到的较小元素后面的所有元素,以确保我们获得的是下一个字典序排列。

完整代码(1)

#include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>using namespace std;// 用于打印一个排列
void printPermutation(const vector<int>& perm) {for (int num : perm) {cout << setw(5) << num; // 每个数字占5个字符宽度}cout << endl;
}int main() {int n;cin >> n; vector<int> perm(n);for (int i = 0; i < n; ++i) {perm[i] = i + 1; // 初始化向量,使其包含1到n}printPermutation(perm); // 先打印初始排列while (next_permutation(perm.begin(), perm.end())) { // 使用 next_permutation 在while循环中生成并打印从1到n的全排列printPermutation(perm);}return 0;
}

解题思路(2)

  1. 主函数(main):

    • 通过 cin >> n; 获取用户输入的整数 n,这个整数表示要生成从1到n的全排列。
    • 接着调用 dfs(0); 开始深度优先搜索(DFS),以生成所有可能的排列。这里从第0位开始搜索,尽管实际上排列中的位是从1开始的,这样做是为了在递归中处理方便。
  2. 深度优先搜索函数(dfs):

    • 这个函数用于生成全排列,并采用递归的方式实现。
    • dfs 函数接收一个参数 k,表示当前正在尝试填充第 k+1 位(因为数组索引从0开始,但排列从1开始)。
    • 如果 k == n,意味着已经成功生成了一个从1到n的排列,因为每个数字都被使用了一次,此时会调用 printPermutation() 函数打印当前的排列。
    • 如果 k < n,则循环从1到n,尝试每个数字。如果某个数字 i 尚未被使用(即 isUsed[i] 为0),则执行以下步骤:
      • i 标记为已使用,即 isUsed[i] = 1
      • 将这个数字 i 放入当前排列的第 k+1 位,即 currentPermutation[k + 1] = i
      • 递归调用 dfs(k + 1) 来填充下一位。
      • 回溯:递归调用返回后,撤销 i 的使用标记,即 isUsed[i] = 0,以便这个数字可以在其他位置被使用。
  3. 打印排列函数(printPermutation):

    • 当一个排列完成时,这个函数被调用来输出排列。
    • 它通过循环,对于排列中的每一个位置,使用 cout << setw(5) << currentPermutation[i]; 来打印出每个数字,其中 setw(5) 确保每个数字占据5个字符宽的空间,以保持输出整齐。
    • 打印完一个排列后,使用 cout << endl; 换行,以便开始打印下一个排列。

完整代码(2)

#include <iostream> // 替代 #include<bits/stdc++.h>,仅包含输入输出相关功能
#include <iomanip>
using namespace std;int n, isUsed[100], currentPermutation[100]; // `isUsed`用于判断某个数是否已经被使用,`currentPermutation`用于存储当前的排列void printPermutation() {for (int i = 1; i <= n; i++) {cout << setw(5) << currentPermutation[i];}cout << endl;
}void dfs(int k) { // 深度优先搜索函数,当前填充第k位if (k == n) { // 如果已填满所有位printPermutation(); // 打印当前排列return;}for (int i = 1; i <= n; i++) { // 尝试每个可能的数字1-nif (!isUsed[i]) { // 如果当前数字尚未使用isUsed[i] = 1; // 标记为已使用currentPermutation[k + 1] = i; // 将当前数字放入排列中dfs(k + 1); // 继续填充下一个位置isUsed[i] = 0; // 回溯,撤销当前数字的使用标记}}
}int main() {cin >> n; dfs(0); // 从第0位开始进行深度优先搜索return 0;
}

这篇关于【CSP考题扩展】暴力枚举(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/823846

相关文章

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

计蒜客 Half-consecutive Numbers 暴力打表找规律

The numbers 11, 33, 66, 1010, 1515, 2121, 2828, 3636, 4545 and t_i=\frac{1}{2}i(i+1)t​i​​=​2​​1​​i(i+1), are called half-consecutive. For given NN, find the smallest rr which is no smaller than NN

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

【Rust练习】12.枚举

练习题来自:https://practice-zh.course.rs/compound-types/enum.html 1 // 修复错误enum Number {Zero,One,Two,}enum Number1 {Zero = 0,One,Two,}// C语言风格的枚举定义enum Number2 {Zero = 0.0,One = 1.0,Two = 2.0,}fn m

枚举相关知识点

1.是用户定义的数据类型,为一组相关的常量赋予有意义的名字。 2.enum常量本身带有类型信息,即Weekday.SUN类型是Weekday,编译器会自动检查出类型错误,在编译期间可检查错误。 3.enum定义的枚举类有什么特点。         a.定义的enum类型总是继承自java.lang.Enum,且不能被继承,因为enum被编译器编译为final修饰的类。         b.只能定义

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[