相信大家都遇到過,包括各種算法比賽,經常會遇到求一組數據或者單個事物或者多個事物全排列和組合的問題,那麼我們該如何求呢?下面我分享給大家排列組合:
一:全排列
#include<stdio.h>
#include<string.h>
void f(char a[],int k){
int i,length;
length=strlen(a); //計算字符串的長度
if(k==length-1){
printf("%s",a); //打印字符數組a
printf("\n");
return ;
}
char t;
for(i=k;i<length;i++){
{
//試探
t=a[k]; a[k]=a[i];a[i]=t;
}
f(a,k+1);
{
//回溯 :把上一級改變的再改變過來,防止下次遞歸改變a的值時,已經不是初始的a
t=a[k]; a[k]=a[i];a[i]=t;
}
}
}
int main(){
char a[4]={'A','B','C'}; //初始化字符數組a
f(a,0);
return 0;
}
二:組合問題
1.不重複的情況:
例如ABCDE,讓你從裏面選出3個,問你一共有多少種可能,我們可以直接遞歸進行列舉一共有多少種。下面看代碼:
#include<stdio.h>
//元素個數不重複
int f(int m,int n){
if(n==m){ //我們一直從堆裏拿球,當拿到,堆裏的球和我們想要拿的球數相同,只要一種情況。
return 1;
}
if(n==0){ //當我們從堆裏取出0個時,從數學角度上,這也是一種取法。
return 1;
}
/*
假設堆裏有個特殊的球,兩種情況:要麼這個球就是我們要取的,那麼我們從m-1個球裏再取n-1個,如果不是,那麼我們從m-1個球裏取出n個,一直這樣遞歸下去。
*/
return f(m-1,n)+f(m-1,n-1);
}
int main(){
printf("%d",f(5,3)); //5代表ABCDE這5個字母,3代表從中取三個。
return 0;
}
```C
2.重複的情況:
例如AABBBC ,讓你從這些字母中選出三個進行組合,你肯定不能枚舉,這樣你會發現打印出來有重複的。因爲元素有相同的。所以這個時候要選擇另外一種方式:
```c
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
/*
data:不動,限制條件
x:取法
k:當前考慮的位置
goal:距離目標的剩餘名額
注意:
這是針對取的元素中有相同的
*/
int min(int a,int b){
if(a>b){
return b;
}
return a;
}
void work(int x[]){
int i;
for(i=0;i<3;i++){
printf("%d",x[i]);
}
printf("\n");
}
void f(int data[],int x[],int k,int goal){
int i;
if(k==3){
if(goal==0){
work(x);
}
return ;
}
for(i=0;i<=min(data[k],goal);i++){
x[k]=i;
f(data,x,k+1,goal-i);
}
x[k]=0;//回溯
}
int main(){
int i;
int data[3]={2,3,1}; //每個元素的最大個數
int x[3]; //每個元素取幾個
f(data,x,0,3);
return 0;
}
如果喜歡我的博客,點個贊吧!!!!!!!!!!!