排列组合问题
2011-05-04 11:42
183 查看
1. 基本排列A(n, m)的实现
1)应用穷举是比较容易实现的
2)这里用回溯法解决此题(回溯法简介http://baike.baidu.com/view/45.htm)
算法思路:
①设置一维a数组,a在1~n中取值,出现数字相同时返回
②当i<m时,还未取m个数,i增加1后a(i)=1继续;当i=m时,输出一个A(n, m)的排列,并设置变量s统计A(n, m)排列的个数(这个其实可以用数学公式直接计算
③当a(i)<n时a(i)增1继续;当a(i)=n时回溯或调整,直到i=0时结束。
3)代码
4)程序变通
①若将a[j]==a修改为a[j]>=a就能实现从n个不同元素中取m个的组合
②把以上程序中的输出语句“printf("%d", a[j])“改为“printf("%c", a[j]+64)”,排列(或组合)输出由前n个整数改变为前n个大写英文字母输出。
③将该语句改成printf("%c", n+65-a[j]),排列(或组合)输出由前n个正整数改变为前n个大写英文字母逆序输出。
2.特殊情况
问题描述:从n个不同元素中取m个元素与另n-m个相同元素的排列,如:如何从4个不同数字1、2、3、4中取2个数字与另2个“0”的排列?
一般地,探讨实现从n个不同元素中取m(约定1<m<=n)个元素与另外n-m个相同元素组成的排列。
设n个不同元素为数字1~n,n-m个相同元素为n-m个元素0.
设置一维数组,应用回溯法产生由数字0~n这n+1个元素取n个数字组成的n元组,若非0元素(即数字1~n)有重复时舍去;引入了一个变量k来控制0的个数,使它不超过n-m。余下的即从数字1~n中取m个不同数字与n-m个0的排列,进行打印出来
1)应用穷举是比较容易实现的
2)这里用回溯法解决此题(回溯法简介http://baike.baidu.com/view/45.htm)
算法思路:
①设置一维a数组,a在1~n中取值,出现数字相同时返回
②当i<m时,还未取m个数,i增加1后a(i)=1继续;当i=m时,输出一个A(n, m)的排列,并设置变量s统计A(n, m)排列的个数(这个其实可以用数学公式直接计算
③当a(i)<n时a(i)增1继续;当a(i)=n时回溯或调整,直到i=0时结束。
3)代码
// ICPC.cpp : 定义控制台应用程序的入口点。 // 排列组合 #include "stdafx.h" // 基本排列A(n, m)的实现 int _tmain(int argc, _TCHAR* argv[]) { int n, m, i, j, flag, a[30]; long s = 0; printf("排列的实现,A(n, m)/n"); printf("Input n(n<10) and m(1<m<=n): /n"); scanf("%d%d", &n, &m); i = 1; a[1] = 1; while (1) { flag = 1; for (j = 1; j < i; j++) if (a[j] == a[i]) // 出现相同元素时返回 { flag = 0; break; } if (flag && i == m) { s++; for (j = 1; j <= m; j++) printf("%d", a[j]); printf(" "); } if (flag && i < m) { i++; a[i] = 1; continue; } while (a[i] == n) i--; // 调整或回溯或终止 if (i > 0) a[i]++; else break; } printf("/ns=%ld/n", s); return 0; }
4)程序变通
①若将a[j]==a修改为a[j]>=a就能实现从n个不同元素中取m个的组合
②把以上程序中的输出语句“printf("%d", a[j])“改为“printf("%c", a[j]+64)”,排列(或组合)输出由前n个整数改变为前n个大写英文字母输出。
③将该语句改成printf("%c", n+65-a[j]),排列(或组合)输出由前n个正整数改变为前n个大写英文字母逆序输出。
2.特殊情况
问题描述:从n个不同元素中取m个元素与另n-m个相同元素的排列,如:如何从4个不同数字1、2、3、4中取2个数字与另2个“0”的排列?
一般地,探讨实现从n个不同元素中取m(约定1<m<=n)个元素与另外n-m个相同元素组成的排列。
设n个不同元素为数字1~n,n-m个相同元素为n-m个元素0.
设置一维数组,应用回溯法产生由数字0~n这n+1个元素取n个数字组成的n元组,若非0元素(即数字1~n)有重复时舍去;引入了一个变量k来控制0的个数,使它不超过n-m。余下的即从数字1~n中取m个不同数字与n-m个0的排列,进行打印出来
// ICPC.cpp : 定义控制台应用程序的入口点。 // 排列组合 #include "stdafx.h" #define MAXN 30 // 一般情况排列A(n, m)的实现 // 从n个不同元素中取m个元素与n-m个相同元素的排列 int _tmain(int argc, _TCHAR* argv[]) { int n, m, a[MAXN]; int i, j, k, flag; // k用于控制0的个数 long s = 0; // 统计总共个数 printf("排列组合的一般情况:/n"); printf("从n个不同元素中取m个元素与n-m个相同元素的排列:/n"); printf("Input n and m: "); scanf("%d%d", &n, &m); i = 1; a[1] = 0; k = 1; while (1) { flag = 1; for (j = 1; j < i; j++) if (a[j] && a[j] == a[i]) { flag = 0; break; } if (flag && k == n - m && i == n) { s++; for (j = 1; j <= n; j++) printf("%d", a[j]); printf(" "); } if (flag && (k < n - m || i < n)) { i++; if (k < n-m) { a[i] = 0; k++; } else a[i] = 1; continue; } while (a[i] == n) // 调整或回溯或终止 i--; if (i > 0) { if (!a[i]) k--; a[i]++; } else break; } printf("/ns=%ld/n", s); return 0; }
相关文章推荐
- 字符串的排列组合问题
- C/C++ 排列组合问题(递归)
- 算法 全排列问题,组合问题,子集问题
- TODO:排列组合问题:n个数中取m个
- 递归求解几类排列组合问题(二、全组合排列)
- c/c++算法 排列组合问题
- Java解决排列组合问题——深度优先遍历
- 四个数的排列组合问题
- 字符串的全排列和组合递归非递归--排列组合扩展问题
- 递归求解几类排列组合问题(四、普通选择性组合排列)
- LeetCode排列组合问题合集
- 汉诺塔问题推广【排列组合】
- Oracle SQL排列组合之组合问题
- c语言实现排列组合算法问题
- 字符串的排列组合问题
- 排列组合问题之圆形分布
- java实现字符串排列组合问题
- Java解决排列组合问题——深度优先遍历
- 两元素交换的排列组合问题
- 排列组合问题