タスクを実装しようとしています。円上に 2*n 点があります。したがって、それらの間に n 個の和音を作成できます。n 個の交差しない弦を描くすべての方法を出力してください。
例: n = 6 の場合、(1->2 3->4 5->6)、(1->4、2->3、5->6)、(1->6、2 ->3, 4->5), (1->6, 2->5, 3->4)
1-> 2、4、6 から和音を作成し、残りの 2 つの間隔の答えを生成することにより、再帰アルゴリズムを開発しました。しかし、より効率的な非再帰的な方法があることは知っています。NextSeq 関数を実装することによる可能性があります。
誰にもアイデアはありますか?
UPD:私は中間結果をキャッシュしますが、本当に欲しいのは、前のシーケンスによって次のシーケンスを生成できる GenerateNextSeq() 関数を見つけて、そのようなすべての組み合わせを生成することです
ちなみにこれは私のコードです
struct SimpleHash {
size_t operator()(const std::pair<int, int>& p) const {
return p.first ^ p.second;
}
};
struct Chord {
int p1, p2;
Chord(int x, int y) : p1(x), p2(y) {};
};
void MergeResults(const vector<vector<Chord>>& res1, const vector<vector<Chord>>& res2, vector<vector<Chord>>& res) {
res.clear();
if (res2.empty()) {
res = res1;
return;
}
for (int i = 0; i < res1.size(); i++) {
for (int k = 0; k < res2.size(); k++) {
vector<Chord> cur;
for (int j = 0; j < res1[i].size(); j++) {
cur.push_back(res1[i][j]);
}
for (int j = 0; j < res2[k].size(); j++) {
cur.push_back(res2[k][j]);
}
res.emplace_back(cur);
}
}
}
int rec = 0;
int cached = 0;
void allChordsH(vector<vector<Chord>>& res, int st, int end, unordered_map<pair<int, int>, vector<vector<Chord>>, SimpleHash>& cach) {
if (st >= end)
return;
rec++;
if (cach.count( {st, end} )) {
cached++;
res = cach[{st, end}];
return;
}
vector<vector<Chord>> res1, res2, res3, curRes;
for (int i = st+1; i <=end; i += 2) {
res1 = {{Chord(st, i)}};
allChordsH(res2, st+1, i-1, cach);
allChordsH(res3, i+1, end, cach);
MergeResults(res1, res2, curRes);
MergeResults(curRes, res3, res1);
for (auto i = 0; i < res1.size(); i++) {
res.push_back(res1[i]);
}
cach[{st, end}] = res1;
res1.clear(); res2.clear(); res3.clear(); curRes.clear();
}
}
void allChords(vector<vector<Chord>>& res, int n) {
res.clear();
unordered_map<pair<int, int>, vector<vector<Chord>>, SimpleHash> cach; // intrval => result
allChordsH(res, 1, n, cach);
return;
}