首页 > 代码库 > 第二章-递归与分治策略
第二章-递归与分治策略
第一题:
问题名称:整数划分问题。
问题描述:正整数n可以表示为一系列正整数之和:n = n1 + n2 + ... + nk (k>=1, n1>=n2>=nk ),则称这种表示为正整数n的划分,不同的这种表示的个数称为正整数n的划分数,记为p(n)。在所有划分中,将最大加数n1不大于m的划分数,记为q(n,m)。
问题分析:
q(n, m) = 1 ,当n = 1,m = 1;
q(n,n) ,当n < m;
1 + q(n,n-1),当n = m;
q(n,m-1) + q(n-m,m),当n>m>1
所以得出算法:
1 #include <stdio.h> 2 3 int Division(int n, int m); 4 void main() 5 { 6 int n = 0; 7 scanf("%d", &n); 8 printf("%d\n",Division(n, n)); 9 } 10 11 int Division(int n, int m) 12 { 13 if( ( n < 1 ) || ( m < 1 ) ) return 0; 14 if( ( n == 1 ) || ( m == 1 ) ) return 1; 15 if( n < m ) return Division(n, n); 16 if( n == m ) return Division(n, m - 1 ) + 1; 17 return Division(n, m - 1) + Division(n - m, m); 18 }
有重复元素的排列问题:
给定一个集合R={r1, ... , rn},其中的元素可能相同。求R的所有不同的排列。
算法分析:
输出的排列有重复,是因为输入的集合可能含有重复的元素。首先要学会演算,在演算的过程中,可以发现,如果递归的每一层,对于不同的递归/排列(这个就要在isRepeat函数中理解了),出现重复元素,那么产生的两个分支是完全一样的。——所以出现重复元素,那么此次就不用排列了,因为前面已经有了。
设Ri=R-{ri},集合X的全排列(所有排列)为Perm(X),而(ri)Perm(Ri)表示在Perm(Ri)的所有排列前面加上ri。
所以,R的全排列可以定义为:
- 出口:当n=1时,Perm(R) = r 。
- 产生递归:当n>1时,Perm(R) = (r1)Perm(R1),(r2)Perm(R2),... ,(rn)Perm(Rn)组成。
输入:第一行为元素个数n,第二行为待排列的n个数。
输出:前面几行是所有的不同的排列,最后一行是排列的总数。
代码:
#include <iostream> #include <algorithm> using namespace std; int permNumber = 0; bool isRepeat(char *R, int i, int k) { for (int j = k; j < i; j++) { if (R[i] == R[j]) return true; } return false; } void Perm(char *R, int k, int m) { if (k == m) //到最后一个元素,出口 { for (int i = 0; i <= m; i++) //因为在递归的过程中,m为变换,所以就是传进来的n-1 { cout << R[i]; } cout << endl; permNumber++; } else { for (int i = k; i <= m; i++) { if (!isRepeat(R, i, k)) { swap(R[k], R[i]); Perm(R, k + 1, m); //k就代表递归层数,即指向数组的位置 swap(R[k], R[i]); } } } } int main() { int n; char *R; cin >> n; R = new char[n]; for (int i = 0; i < n; i++) { cin >> R[i]; } cout << endl; Perm(R, 0, n - 1); cout << permNumber << endl; return 0; } /*测试数据: 输入: 4 aacc 输出: aacc acac acca caac caca ccaa 6 */
第二章-递归与分治策略
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。