在Project Euler's problem 67中,给出了一个三角形,它包含100行。例如,
5
9 6
4 6 8
0 7 1 5
I.e. 5 + 9 + 6 + 7 = 27.
现在我必须在给定的100行三角形中找到从上到下的最大总数。
我在考虑应该使用哪种数据结构,以便有效地解决问题。
答案 0 :(得分:4)
您希望将其存储为directed acyclic graph。节点是三角形数组的条目,并且i
到j
的箭头如果j
低于i
的左下一行。< / p>
现在您想在此图中找到maximum weight directed path(顶点权重之和)。一般来说,这个问题是NP完全的,然而,正如templatetypedef所指出的,DAG有一些有效的算法; here's one:
algorithm dag-longest-path is
input:
Directed acyclic graph G
output:
Length of the longest path
length_to = array with |V(G)| elements of type int with default value 0
for each vertex v in topOrder(G) do
for each edge (v, w) in E(G) do
if length_to[w] <= length_to[v] + weight(G,(v,w)) then
length_to[w] = length_to[v] + weight(G, (v,w))
return max(length_to[v] for v in V(G))
为了使这项工作,您需要将路径的length
加权为目标节点的大小(因为所有路径都包含源,这很好)。
答案 1 :(得分:1)
您使用的是哪种语言?
多维数组可能是存储值的最佳方法,然后根据语言的不同,您可以选择存储指针或引用数组中的位置。
答案 2 :(得分:1)
为了建立@Matt Wilson的答案,使用二维数组来保存数字将是一个相当简单的解决方案。在您的情况下,您将编码三角形
5
9 6
4 6 8
0 7 1 5
作为数组
[5][ ][ ][ ]
[9][6][ ][ ]
[4][6][8][ ]
[0][7][1][5]
从这里开始,位置(i,j)处的节点在(i + 1,j)和(i + 1,j + 1)处具有子节点,在位置(i-1,j)处具有父节点,并且(i - 1,j - 1),假设这些指数有效。
这种方法的优点是,如果你的三角形有高度N,这种方法所需的空间是N 2 ,这只是N(N + 1)/ 2空间的两倍需要实际存储元素。像显式图这样的链接结构肯定会使用更多的内存。
答案 3 :(得分:0)
我认为这是项目欧拉问题。
无法用二叉树表示。任何类型的图形都是过度的,尽管问题可以通过有向非循环图中的最长路径算法来解决。编辑:没关系,只有在边加权时才有用,而不是节点。
二维向量(例如vector<vector<int> >
)足以表示这样的三角形,并且使用这种表示有一种直接的解决方案。
答案 4 :(得分:0)
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
int main() {
std::vector<std::vector<int> > lines;
lines.resize(100);
std::ifstream input("triangle.txt");
for (int i = 0; i < 100; i++) {
for (int j = 0; j < i + 1; j++) {
std::string number_string;
input >> number_string;
std::istringstream temp(number_string);
int value = 0;
temp >> value;
lines[i].push_back(value);
}
}
std::vector<int> path1;
path1.resize(100);
std::vector<int> path2;
path2.resize(100);
for (int i = 0;i < 100;i++)
path1[i] = lines[99][i];
for (int i = 98; i >= 0;i--) {
for(int j = 0;j < i+1;j++) {
if(path1[j] > path1[j + 1]){
path2[j] = path1[j] + lines[i][j];
} else{
path2[j] = path1[j + 1] + lines[i][j];
}
}
for (int i = 0;i < 100;i++)
path1[i] = path2[i];
}
std::cout << path1[0] << std::endl;
}