gpt4 book ai didi

algorithm - 回溯算法的复杂度

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

我尝试使用回溯来解决这个问题,但我不确定算法的复杂性(以及算法是否正确)以及复杂性更好的算法。

给定 2 个正整数 n 和 m,如果满足以下条件,我们称其为合法的整数序列:

  • 序列的长度为n
  • 序列中的元素在1到m之间
  • 序列中位置i的元素,1 < i <= n,是位置i-1元素的约数

统计合法序列的个数。算法的预期复杂度为 O(m² + nm)

这是我在 c 中的算法:

// n length of the sequence
// m maximum valid number
// l number of remaining positions in the sequence
// p previous number in the sequence

int legal(int n, int m, int l, int p) {
if (l == 0)
return 1;
int q=0;
for (int i=1; i <= m;i++) {
if (p%i == 0 || l == n)
q += legal(n,m,l-1,i);
}
return q;
}

int main() {
int n, m;
scanf("%d", &n);
scanf("%d", &m);
printf("%d\n", legal(n,m,n,0));
}

我认为我的算法的复杂度是 O(nmS(n)) 其中 S(n) = 合法序列的数量

最佳答案

您的程序在问题的解空间中运行是正确的。对于此类问题,您的解决方案对于大输入(比如 n = m = 100)不是最优的。这是因为解决方案空间相对于 mn 呈指数增长。这是一个使用 memoization 的解决方案避免重新计算:

#include <cstdio>

#define LIMIT 101
#define DIRTY -1


long long cache[LIMIT][LIMIT];

void clear_cache() {
for (int i = 0; i < LIMIT; i++) {
for (int j = 0; j < LIMIT; j++) {
// marked all entries in cache as dirty
cache[i][j] = DIRTY;
}
}
}

long long legal_seqs(int curr_len, int prev_num, int seq_len, int max_num) {
// base case
if (curr_len == seq_len) return 1;

// if we haven't seen this sub-problem, compute it!
// this is called memoization
if (cache[curr_len][prev_num] == DIRTY) {
long long ways = 0;
// get all multiples of prev_num
for (int next_num = 1; next_num <= max_num; next_num++) {
if (prev_num % next_num == 0) {
ways += legal_seqs(curr_len + 1, next_num, seq_len, max_num);
}
}
cache[curr_len][prev_num] = ways;
}
return cache[curr_len][prev_num];
}

int main() {
int n, m;
scanf("%d%d", &n, &m);
clear_cache();
printf("%lld\n", legal_seqs(0, 0, n, m));
}

上面的代码以您提到的时间复杂度运行。

关于algorithm - 回溯算法的复杂度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44547302/

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