初入算法篇(递推)错排公式

本文探讨了错排问题,即n封信放入n个特定信封时全部放错的情况数。通过递推公式s[n]=(n-1)*(s[n-1]+s[n-2])进行计算,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

将n封信放入n个信封,每一封信对应一个特定的信封,那么如果n封信全部放错的组合有多少种

当n个元素放入n个特定位置,我们用s[n]来表示n封信放入n个位置,s[n-1]表示n-1封信放入n-1个位置,我们假设将第n封信放入第k个位置,那么总共有n-1个选择,接着对于n位置我们有两种情况

1.如果将第k封信放入第n个位置,即n和k互相放反了,那么对于全局来说,我们只剩下n-2封信了,即s[n-2]

2.如果第k封信不放入第n个位置,即我们还有n-1个元素没有放,我们有s[n-1]种方法

故总共方程可列出s[n]=(n-1)*(s[n-1]+s[n-2])边界s[1]=0;s[2]=1;

这题目纯粹是掌握公式,学会更多的东西

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;
long long s[1009];
int main()
{
    s[0]=0;
    s[1]=0;//没有错排可能
    s[2]=1;
    int i,n;
    for(i=3;i<=1000;i++)
    {
        s[i]=(i-1)*(s[i-1]+s[i-2]);
    }
    scanf("%d",&n);
    printf("%lld",s[n]);
}

在C++中,问题通常是指对数组进行全列的问题。这里我将分别介绍递归算法和迭代算法的实现。 **递归算法** (也称回溯法): ```cpp #include <iostream> using namespace std; void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } void permuteRecursion(int arr[], int start, int end) { if (start == end) cout << arr << endl; else { for (int i = start; i <= end; i++) { swap(&arr[start], &arr[i]); permuteRecursion(arr, start + 1, end); // 撤销当前交换,回到上一步状态 swap(&arr[start], &arr[i]); } } } void generatePermutations(int n) { int* arr = new int[n]; for (int i = 0; i < n; i++) arr[i] = i + 1; permuteRecursion(arr, 0, n - 1); delete[] arr; } int main() { int n; cout << "Enter the size of the array: "; cin >> n; generatePermutations(n); return 0; } ``` **迭代算法** (也称为栈回溯法): ```cpp #include <iostream> #include <vector> using namespace std; void generatePermutations(vector<int>& nums, vector<vector<int>>& results, int index) { if (index == nums.size()) { results.push_back(nums); return; } for (int i = 0; i < nums.size(); ++i) { // 交换当前元素的位置 swap(nums[index], nums[i]); // 继续处理剩余元素 generatePermutations(nums, results, index + 1); // 回溯,恢复到原始位置 swap(nums[index], nums[i]); // 这里也可以选择不恢复,取决于需求 } } vector<vector<int>> permuteIterative(int n) { vector<int> nums(n), res; for (int i = 0; i < n; i++) nums[i] = i + 1; vector<vector<int>> results; generatePermutations(nums, results, 0); return results; } int main() { int n; cout << "Enter the size of the array: "; cin >> n; auto permutations = permuteIterative(n); for (const auto& p : permutations) cout << p << endl; return 0; } ``` 在这两个示例中,递归算法通过不断交换并尝试所有可能性直到达到结束条件(只有一个元素),而迭代算法则是通过维护一个结果列表并在每次循环结束后回溯来避免重复。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值