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 : 定義控制台應用程式的進入點。<br />// 排列組合</p><p>#include "stdafx.h"</p><p>// 基本排列A(n, m)的實現<br />int _tmain(int argc, _TCHAR* argv[])<br />{<br />int n, m, i, j, flag, a[30];<br />long s = 0;</p><p>printf("排列的實現,A(n, m)/n");<br />printf("Input n(n<10) and m(1<m<=n): /n");<br />scanf("%d%d", &n, &m);</p><p>i = 1; a[1] = 1;<br />while (1)<br />{<br />flag = 1;<br />for (j = 1; j < i; j++)<br />if (a[j] == a[i])// 出現相同元素時返回<br />{<br />flag = 0;<br />break;<br />}<br />if (flag && i == m)<br />{<br />s++;<br />for (j = 1; j <= m; j++)<br />printf("%d", a[j]);<br />printf(" ");<br />}<br />if (flag && i < m)<br />{<br />i++;<br />a[i] = 1;<br />continue;<br />}<br />while (a[i] == n)<br />i--;// 調整或回溯或終止<br />if (i > 0)<br />a[i]++;<br />else<br />break;<br />}</p><p>printf("/ns=%ld/n", s);</p><p>return 0;<br />}</p><p>
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 : 定義控制台應用程式的進入點。<br />// 排列組合</p><p>#include "stdafx.h"</p><p>#define MAXN 30</p><p>// 一般情況排列A(n, m)的實現<br />// 從n個不同元素中取m個元素與n-m個相同元素的排列<br />int _tmain(int argc, _TCHAR* argv[])<br />{<br />int n, m, a[MAXN];<br />int i, j, k, flag;// k用於控制0的個數<br />long s = 0;// 統計總共個數</p><p>printf("排列組合的一般情況:/n");<br />printf("從n個不同元素中取m個元素與n-m個相同元素的排列:/n");<br />printf("Input n and m: ");<br />scanf("%d%d", &n, &m);</p><p>i = 1; a[1] = 0; k = 1;<br />while (1)<br />{<br />flag = 1;<br />for (j = 1; j < i; j++)<br />if (a[j] && a[j] == a[i])<br />{<br />flag = 0;<br />break;<br />}<br />if (flag && k == n - m && i == n)<br />{<br />s++;<br />for (j = 1; j <= n; j++)<br />printf("%d", a[j]);<br />printf(" ");<br />}<br />if (flag && (k < n - m || i < n))<br />{<br />i++;<br />if (k < n-m)<br />{<br />a[i] = 0;<br />k++;<br />}<br />else<br />a[i] = 1;<br />continue;<br />}<br />while (a[i] == n)// 調整或回溯或終止<br />i--;<br />if (i > 0)<br />{<br />if (!a[i])<br />k--;<br />a[i]++;<br />}<br />else<br />break;<br />}</p><p>printf("/ns=%ld/n", s);</p><p>return 0;<br />}