最长的链条可以安排

时间:2015-08-11 10:37:39

标签: c++ algorithm graph-theory depth-first-search

我在比赛的某个地方发现了这个问题,而且还没有能够提出解决方案。

  

我有正整数。我必须找到其中最长的子集   每两个相邻元素一个除以另一个。

我正在做的是:我正在创建图表。然后我连接其中数字彼此分开的节点。之后我使用DFS(一个节点可以连接两个节点)。

但并非所有测试用例都适用于系统。在使用DFS之前,我是否必须对数组进行排序?也许有特殊的(动态)算法?

测试用例失败:

N = 5
1 1 3 7 13

我的代码提供输出4。但如果我arrange这个数组是这样的:

3 1 7 1 13

输出为5,这是真正的答案。

我也使用了递归方法。但我需要更快的东西。

2 个答案:

答案 0 :(得分:3)

您忘了重新启动一些变量:usedkol。 此外,对于下次调用,DFS不会在结束时恢复used[i]

尽量避免使用全局变量,这会使代码变得不那么清晰。 还要尝试减少变量的范围。

代码可能会看起来像:

void DFS(int (&used)[20], const int (&m)[20][20], int c, int& maxn, int k, int v) {
    used[v] = 1;
    k += 1;
    if(k > maxn)
        maxn = k;
    for(int i = 0; i < c; ++i) {
        if(!used[i] && m[v][i] == 1) {
            DFS(used, m, c, maxn, k, i);
        }
    }
    used[v] = 0;
}

并在主要:

int m[20][20];
memset(m, 0, sizeof(m));

for(int i = 0; i < c; ++i) {
    for(int j = i + 1; j < c; ++j) {
        if( (a[i] % a[j] == 0) || (a[j] % a[i] == 0) ) {
            m[i][j] = m[j][i] = 1; // Creating 2D array
        }
    }
}

int maxn = 0;
for(int i = 0; i < c; ++i) {
    int used[20];
    int k = 0;
    memset(used, 0, sizeof(used));
    DFS(used, m, c, maxn, k, i);
}
std::cout << maxn << std::endl;

Live Demo

代码可能会更加简化(使用vector,...)

答案 1 :(得分:1)

这是最长的路径,略带伪装。我们可以通过准备两个顶点相邻的图来解决这个问题作为最长路径,当且仅当它们满足可分性关系时。请参阅下面的水平规则,以获得指向预期答案的指针。

减少是(粗略地),给定一个无向图,我们希望找到最长的简单路径,为每个顶点分配一个不同的素数。发出这些素数,以及每个边缘,作为其端点的乘积的半素数。 (我们还需要两个素数和它们的2 | V |乘积与顶点素数以保持目标相加。)

例如,如果我们有图表

*---*
|  /|
| / |
|/  |
*---*,

然后我们可以标记

2---3
|  /|
| / |
|/  |
5---7,

然后输入

2, 3, 5, 7,  # vertices
2*3, 2*5, 3*5, 3*7, 5*7,  # edges
11*2, 11*3, 11*5, 11*7,  # sentinels at one end
2*13, 3*13, 5*13, 7*13,  # sentinels at the other end

和(例如)最长路径2, 3, 5, 7对应于最长序列11*2, 2, 2*3, 3, 3*5, 5, 5*7, 7, 7*13(以及涉及反转和交换的其他三个变体1113)。

最长的路径是NP难的,所以nhahtdh关于O(2 ^ n poly(n) - 时间动态程序的评论是正确的 - 看到这个问题和接受的答案:{{ 3}}