ACM經典算法題目
輸入n,輸出1~n的全排列
如輸入:3
輸出:
123
132
……
如圖:
關於這個問題要如何實現呢:
大家可以自己先思考一下,下面我說一下答案。
這其實是一道簡單的深度優先搜索的題目
代碼:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
#define MAX_N 1000
bool used[MAX_N];
int perm[MAX_N];
void permutation1(int pos, int n)
{
if(pos == n)
{
for(int i = 0; i < n; i++)
{
printf("%d ", perm[i]);
}
printf("\n");
return ;
}
for(int i = 0; i < n; i++)
{
if(!used[i])
{
perm[pos] = i;
used[i] = true;
permutation1(pos+1, n);
used[i] = false;
}
}
return ;
}
int main()
{
int n;
scanf("%d", &n);
permutation1(1, n+1);
return 0;
}
結果:
如果對代碼有問題的小夥伴我猜是對這一段代碼塊不理解
for(int i = 0; i < n; i++)
{
if(!used[i])
{
perm[pos] = i;
used[i] = true;
permutation1(pos+1, n);
used[i] = false;
}
}
其實不難:設定一個used數組用來標記當前元素是否已經被訪問,如果沒有被訪問過則進入if代碼塊,將當前元素填入perm數組中(perm數組是用來記錄全排列元素的順序的)並將used數組置爲true,並遞歸調用此函數。那麼問題來了,爲什麼要在後面加一個把used數組又重置爲false呢?其實這就是dfs的回溯(相信有的小夥伴已經明白了)。比如:123下一個排列是132,爲什麼能產生132呢,就是因爲當本次遞歸到出口後,又將used數組重置爲false才能夠繼續訪問2和3,先重置元素3,再重置元素2,這就是回溯。
那麼到這裏還沒有結束,因爲c++標準庫爲我們提供了一種更加便捷的方式(記得要加頭文件algorithm):
代碼:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
#define MAX_N 1000
int perm2[MAX_N];
void permutation2(int n)
{
for(int i = 0; i < n; i++)
{
perm2[i] = i;
}
do{
for(int i = 0; i < n; i++)
printf("%d ", perm2[i]);
printf("\n");
}while(next_permutation(perm2, perm2+n));
return ;
}
int main()
{
int n;
scanf("%d", &n);
permutation2(n);
return 0;
}
結果:
是不是感覺又輕鬆了不少呢!