【发布时间】:2013-09-27 18:10:04
【问题描述】:
假设你有一个包含 n 个变量的线性方程。目标是要么确定不可能有整数解,要么确定整数解的最小系数向量。
换句话说,让ax=b 其中x 是您要查找的向量,a 是系数向量。 b 是一个标量常数。找到x 使得x1, ... ,xn 的和最小化,并且所有xis 都是整数。或者,确定不存在这样的x。从现在开始,我会说|x|是xi的总和。
解决这个问题的有效方法是什么?我觉得这类似于背包问题,但我并不完全确定。
我的解决方案
我试图解决这个问题的方法是对向量空间进行广度优先搜索,其中 breadth 将是向量条目的总和。
一开始我很天真,从|x| = 0开始,但是当n甚至中等大,并且解决方案不平凡时,生成的向量数量是巨大的(n ^ |x|每个|x|你通过)。更糟糕的是,我生成了许多重复项。即使我找到了一种几乎不产生重复的方法,这种方法也太慢了。
接下来,我尝试从更高的|x| 开始,在最佳|x| 上设置下限。我对a 进行了排序,使其按降序排列,然后删除了所有ai > b。那么|x| 的下限是b / a[0]。但是,从这一点开始,我很难快速生成所有大小为|x| 的向量。从这里开始,我的代码大多是 hacky。
在代码中,b = distance、x = clubs、n = numClubs
这是它的样子:
short getNumStrokes (unsigned short distance, unsigned short numClubs, vector<unsigned short> clubs) {
if (distance == 0)
return 0;
numClubs = pruneClubs(distance, &clubs, numClubs);
//printClubs (clubs, numClubs);
valarray<unsigned short> a(numClubs), b(numClubs);
queue<valarray<unsigned short> > Q;
unsigned short floor = distance / clubs[0];
if (numClubs > 1) {
for (int i = 0; i < numClubs; i++) {
a[i] = floor / numClubs;
}
Q.push (a);
}
// starter vectors
for (int i = 0; i < numClubs; i++) {
for (int j = 0; j < numClubs; j++) {
if (i == j)
a[j] = distance / clubs[0];
else
a[j] = 0;
}
if (dot_product (a, clubs) == distance)
return count_strokes(a);
// add N starter values
Q.push (a);
}
bool sawZero = false;
while (! Q.empty ()) {
a = Q.front(); // take first element from Q
Q.pop(); // apparently need to do this in 2 operations >_<
sawZero = false;
for (unsigned int i = 0; i < numClubs; i++) {
// only add numbers past right-most non-zero digit
//if (sawZero || (a[i] != 0 && (i + 1 == numClubs || a[i + 1] == 0))) {
// sawZero = true;
b = a; // deep copy
b[i] += 1;
if (dot_product (b, clubs) == distance) {
return count_strokes(b);
} else if (dot_product (b, clubs) < distance) {
//printValArray (b, clubs, numClubs);
Q.push (b);
}
//}
}
}
return -1;
}
编辑:我使用 valarray 因为我的编译器不符合 C++ 11,所以我不能使用数组。其他代码建议非常感谢。
【问题讨论】:
-
只需使用pseudoinverse?
-
@OliCharlesworth 不要认为我们在数值计算中涵盖了这一点。你能解释一下我 5 岁吗?
-
线性方程存在于线性空间中。由自然数组成的向量不形成线性空间。
-
@BlackSheep:啊,您应该在问题中明确说明!
-
“Bread-First Search” - 我每天早上的例行公事。
标签: c++ algorithm math language-agnostic