我在比赛的某个地方发现了这个问题,而且还没有能够提出解决方案。
我有正整数。我必须找到其中最长的子集 每两个相邻元素一个除以另一个。
我正在做的是:我正在创建图表。然后我连接其中数字彼此分开的节点。之后我使用DFS
(一个节点可以连接两个节点)。
但并非所有测试用例都适用于系统。在使用DFS
之前,我是否必须对数组进行排序?也许有特殊的(动态)算法?
测试用例失败:
N = 5
1 1 3 7 13
我的代码提供输出4
。但如果我arrange
这个数组是这样的:
3 1 7 1 13
输出为5,这是真正的答案。
我也使用了递归方法。但我需要更快的东西。
答案 0 :(得分:3)
您忘了重新启动一些变量:used
和kol
。
此外,对于下次调用,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;
代码可能会更加简化(使用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
(以及涉及反转和交换的其他三个变体11
和13
)。
最长的路径是NP难的,所以nhahtdh关于O(2 ^ n poly(n) - 时间动态程序的评论是正确的 - 看到这个问题和接受的答案:{{ 3}}