生活随笔
收集整理的這篇文章主要介紹了
全排列的递归与非递归形式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2018-3-18
1.遞歸的主要思路是:
n個數的全排列=(n-1個數的全排列)+(另一個數作為前綴)
#include<iostream>
using namespace std;
const int N =
3;
int x[N+
1]={
1,
2,
3};void dfs(
int step,
int end){
if (
step==N){
for (
int i=
0;i<N;i++){cout<<x[i]<<
" ";}cout<<endl;return ;}
for (
int i=
step;i<
end;i++){
int t=x[i];x[i]=x[
step];x[
step]=t;dfs(
step+
1,
end);t=x[i];x[i]=x[
step];x[
step]=t;}
}
int main(){dfs(
0,N); return
0;
}
2.若我們的序列里面有重復的數字呢?去重的全排列就是從第一個數字開始每個數和它后面非重復出現的數字交換。當然這里的重復出現的數字的最后一個會變成非重復的數字的,因而我們這里保證和相同的數字只交換一次。
#include<iostream>
using namespace std;
const int N =
5;
int x[N+
1]={
1,
2,
3,
2,
1};bool res(
int step,
int end){
for (
int i=
step+
1;i<
end;i++){
if (x[i]==x[
step]) return
false;}return
true;
}void dfs(
int step,
int end){
if (
step==N){
for (
int i=
0;i<N;i++){cout<<x[i]<<
" ";}cout<<endl;return ;}
for (
int i=
step;i<
end;i++){
if (res(i,
end)){
int t=x[i];x[i]=x[
step];x[
step]=t;dfs(
step+
1,
end);t=x[i];x[i]=x[
step];x[
step]=t; }}
}
int main(){dfs(
0,N); return
0;
}
3.非遞歸形式就需要我們找規律了…
下一個序列為從右往左找到第一個x[i]<x[i+1]的那個,然后再從右往左找到第一個比x[i]大的數x[j],兩個數進行交換,交換過后將x[i]之后的所有數進行從小到大排序即可。
上一個序列為從右往左找到第一個x[i]&rt;x[i+1]的那個,然后再從右往左找到第一個比x[i]小的數x[j],兩個數進行交換,交換過后將x[i]之后的所有數進行從大到小排序即可。
#include<iostream>
#include<algorithm>
using namespace std;
const int N =
6;
int x[N+
1]={
9,
2,
6,
5,
2,
0};
void next_prime(){
int i,j;
for (i=N-
2;i>=
0;i--) {
if (x[i]<x[i+
1]){
break;} }
for (j=N-
1;j>=
0;j--){
if (x[j]>x[i]){
break;}}
int t=x[j];x[j]=x[i];x[i]=t;sort(x+i+
1,x+N);
}
bool cmp(
int a,
int b){
return a>b;
}
void pre_prime(){
int i,j;
for (i=N-
2;i>=
0;i--) {
if (x[i]>x[i+
1]){
break;} }
for (j=N-
1;j>=
0;j--){
if (x[j]<x[i]){
break;}}
int t=x[j];x[j]=x[i];x[i]=t;sort(x+i+
1,x+N,cmp);
}
void show(){
for (
int i=
0;i<N;i++){
cout<<x[i]; }
cout<<endl;
}
int main(){next_prime();show();pre_prime();show();
return 0;
}
給一個題目吧!
搭積木:
一共有0到9共10個積木,每個積木都有一個數字0~9,每個積木放在兩個積木上面,但是要滿足比下面兩個積木小,搭四層的積木,共有多少搭法。
方法一:
將其看作是一維的,利用全排列把所有情況都表示出來然后再進行判斷,滿足條件就將s+1。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
0,
1,
2,
3,
4,
5,
6,
7,
8,
9};
int s=
0;
bool res(){
if (x[
0]>x[
1]||x[
0]>x[
2])
return false;
if (x[
1]>x[
3]||x[
1]>x[
4])
return false;
if (x[
2]>x[
4]||x[
2]>x[
5])
return false;
if (x[
3]>x[
6]||x[
3]>x[
7])
return false;
if (x[
4]>x[
7]||x[
4]>x[
8])
return false;
if (x[
5]>x[
8]||x[
5]>x[
9])
return false;
return true;
}
void dfs(
int step,
int end){
if (
step==N){
if (res()) s++;
return ;}
for (
int i=
step;i<end;i++){
int t=x[i];x[i]=x[
step];x[
step]=t;dfs(
step+
1,end);t=x[i];x[i]=x[
step];x[
step]=t;}
}
int main(){dfs(
0,N); cout<<s<<endl;
return 0;
}
方法二:
將它看成二維的,逐行逐列進行查看,一旦發現x[c][r]<x[c-1][r-1]或者<x[c][r-1]就continue。
#include<iostream>
#include<cstring>
using namespace std;
const int N =
10, M =
4;
bool f[N+
1];
int x[N+
1][N+
1];
int sum=
0;
void dfs(
int r,
int c){
if (r==M+
1){sum++;
return ;}
if (c==r+
1){dfs(r+
1,
1);
return ;}
for (
int i=
1;i<N;i++){
if (i<x[r-
1][c-
1]||i<x[r-
1][c])
continue;
if (!f[i]){f[i]=
true;x[r][c]=i;dfs(r,c+
1);f[i]=
false;}}
}
int main(){
memset(f,
false,
sizeof(f));dfs(
2,
1);
cout<<sum<<endl;
return 0;
}
總結
以上是生活随笔為你收集整理的全排列的递归与非递归形式的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。