gpt4 book ai didi

algorithm - 圆上不相交弦

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:24:14 25 4
gpt4 key购买 nike

我正在尝试执行任务。我们在圆上有 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;
}

最佳答案

使用动态规划。即缓存部分结果。

基本上,从 1 个和弦开始,计算所有答案并将它们添加到缓存中。然后取 2 个和弦,尽可能使用缓存计算所有答案。等等

递归方式是O(n!)(至少n!,我不擅长复杂度计算)。

这种方式每一步n/2-1次操作,n步,所以O(n^2),这样就好多了。但是,此解决方案依赖于内存,因为它必须在缓存中保存所有组合。 15 和弦轻松使用 1GB 内存(Java 解决方案)。


示例解决方案: https://ideone.com/g81zP9

在 ~306 毫秒内完成 12 和弦计算。给定 1GB 的 RAM,它可以在大约 8 秒内计算出 15 个和弦。

缓存以特定格式保存以优化性能:保存在数组中的数字表示链接有多远。例如 [1,0,3,1,0,0] 表示:

1  0  3  1  0  0
|--| | |--| |
|--------|

您可以在单独的步骤中将其转换为您想要的任何格式。

关于algorithm - 圆上不相交弦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32435853/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com