以下のために書かれた:コース=>検索= 1>タイトル
タイトル説明
正の整数の所定の(\ N-)\を昇順に、デジタル印刷\(1 \)に\(\ N-)すべての順列です。
入力形式
整数\(N-(1 \ N-LE \ル7)\) 。
出力フォーマット
昇順で出力\(\ N-)数のすべての順列、各列は、整列の集合を表し、\(\ N-)二十から百二間のスペースの数を有しています。
サンプル入力
3
サンプル出力
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
分析
これは、検索の対象です。
私たちは、検索が状態への状態間の遷移があることを知って、その本質は、再帰的に列挙型を使用することです(注:この文は非公式の説明であるが、理解しやすいので、我々のようなので、早い段階で理解されます)。
この質問はやる列挙するために使用することができますが、列挙はので、ここで私たちが解決する深さ優先探索を使用し、コードの重複の多くを書くことになります。
私たちは、開くことができans[]
、配列をans[id]
私の現在のポートフォリオが表すためにi
番号を、私は機能開くvoid f(int id)
私の現在のポートフォリオを表すために使用されるが、最初に準備しているid
場所に位置の数を、そして私はちょうど1からnまでトラバースする必要があります番号iは、iが(かどうか、すなわち第一の位置に配置されたIDを見ることができるans[id]
セットi
)。
でid
エネルギー放出位置i
、場合に限り:ans[1]
にans[id-1]
両方の要素i
、すなわち、i
行かせていません。
私たちは時にこのように、f(id)
横断id>n
配置をする際、明らかなように見つけ、出力が可能。
次のようにコードは次のとおりです。
#include<bits/stdc++.h>
using namespace std;
int n, ans[8]; // ans[i]表示当前排列的第i个数是啥
void f(int id) { // 用于在ans[]数组的第id个位置放数
if (id > n) { // 边界条件,说明n个数的一个排列找到了
for (int i = 1; i <= n; i ++)
cout << (i > 1 ? " " : "") << ans[i];
cout << endl;
return; // 输出后返回,不需要继续进行判断了
}
for (int i = 1; i <= n; i ++) { // 尝试在ans[id]放i
bool flag = true;
for (int j = 1; j < id; j ++)
if (ans[j] == i) { // 说明ans[]数据的第j个位置已经放过i了
flag = false;
break;
}
if (flag) { // flag为true说明i可以放
ans[id] = i;
f(id+1); // 递归地放下一个位置
}
}
}
int main() {
cin >> n;
f(1);
return 0;
}
追加の知識
ここで私はまた説明するプログラムの完全な配列を実装しますが、この方法では達成するために、検索を使用していないが、各時間その次の順に電流配置の転換。たとえば、次のように1 2 3 4
変換が一度になり1 2 4 3
、変換がなり、再び1 3 2 4
、ケースのサイクルで......
手動でこのプログラムを実行するために書かれたことができますが、我々は使うためにここにいるalgorithm
私たちの既存の機能が利用可能なライブラリを- next_permutation
。
たとえば、私たちに配列を与えるためにa[5] = {1, 2, 3, 4, 5}
、私たちは再びそれを行う必要がありnext_permutation(a, a+5)
、この配列a[]
にその次の完全な配列になります値を{1, 2, 3, 5, 4}
。
さらに、next_permutation
戻り値があるbool
タイプは、現在、次の配列を配置している場合、それが返され呼び出し、true
現在の配置は、連続配列に変換しながら、既に現在の配置内部最後の順列完全な配列(例えば場合ならば、a[5]={5, 4, 3, 2, 1}
それは既に最終の内部に配置され、完全な配列)であり、それが返されますfalse
。
使用してnext_permutation
、次のように置換コードの全体の問題を解決するための機能は以下のとおりです。
#include<bits/stdc++.h>
using namespace std;
int n, a[] = { 1, 2, 3, 4, 5, 6, 7 };
void output() {
for (int i = 0; i < n; i ++)
cout << (i ? " " : "") << a[i];
cout << endl;
}
int main() {
cin >> n;
do output(); while (next_permutation(a, a+n));
return 0;
}
なぜ私は内部のコードを使用してください:について考えdo...while
ではなく、ループwhile
サイクル。