您的位置:首页 > 其它

排列组合问题

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)代码

// 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: