我正在寻找一种算法来找到两个整数值x,y
,使得它们的产品尽可能接近给定的双k
,而它们的差异很小。
示例:矩形区域为k=21.5
,我希望找到该矩形的边长,其约束条件必须是整数,在这种情况下可能是一些解决方案(不包括排列)(x=4,y=5)
,(x=3,y=7)
和愚蠢的解决方案(x=21,y=1)
事实上,对于(3,7)
夫妻,我们与(21,1)
夫妻有着相同的差异
21.5-3*7=0.5 = 21.5-21*1
而(4,5)
夫妇
21.5-4*5=1.5
但是情侣(4,5)
更可取,因为他们的差异是1
,因此矩形是“更加平方”。
是否有方法提取差异最小的x,y
值,其产品与k的差异也很小?
答案 0 :(得分:3)
您必须查看相关数字的平方根。对于21.5 sqrt(21.5)= 4.6368,实际上你找到的数字就在这个值附近。
答案 1 :(得分:2)
您想要最小化
您提供了一个示例,其中这些目标相互矛盾。 3×7 比 4×5 更接近 21 ,但后者因素更为正方形。因此,不能有任何同时使两者最小化的算法。
您可以对两个目标进行加权并将它们转换为一个,然后通过non-linear integer programming解决问题:
min c × |X × Y - P| + d × |X – Y|
subject to X, Y ∈ ℤ
X, Y ≥ 0
其中 c,d 是非负数,用于定义您评估的目标值。
答案 2 :(得分:1)
取平方根,一个整数,然后另一个整数。
#include <iostream>
#include <cmath>
int main(){
double real_value = 21.5;
int sign = real_value > 0 ? 1 : -1;
int x = std::floor(std::sqrt(std::abs(real_value)));
int y = std::ceil(std::sqrt(std::abs(real_value)));
x *= sign;
std::cout << x << "*" << y << "=" << (x*y) << " ~~ " << real_value << "\n";
return 0;
}
请注意,这种方法只能让您在x
和y
之间保持良好的距离,例如real_value = 10
然后x=3
和y=4
,但产品是12
。如果你想在产品和实际价值之间取得更好的距离,你必须调整整数并增加它们的差异。
答案 3 :(得分:0)
让双给K。
取K的地板,让它成为F.
取两个大小为F * F的整数数组。让他们成为Ar1,Ar2。
像这样运行循环
int z = 0 ;
for ( int i = 1 ; i <= F ; ++i )
{
for ( int j = 1 ; j <= F ; ++j )
{
Ar1[z] = i * j ;
Ar2[z] = i - j ;
++ z ;
}
}
您现在可以获得所有可能数字的差异/产品对。现在为产品接近值K分配一些“优先级值”,为其他一些分配较小的差异。现在遍历这些数组从0到F * F,并通过检查您的条件找到您需要的对。
例如。让我们更接近K的优先级为1,差异越小则优先级为.5。考虑另一个大小为F * F的阵列Ar3。然后,
for ( int i = 0 ; i <= F*F ; ++i )
{
Ar3[i] = (Ar1[i] - K)* 1 + (Ar2[i] * .5) ;
}
遍历Ar3以找到最大值,即您正在寻找的对。
答案 4 :(得分:0)
double best = DBL_MAX;
int a, b;
for (int i = 1; i <= sqrt(k); i++)
{
int j = round(k/i);
double d = abs(k - i*j);
if (d < best)
{
best = d;
a = i;
b = j;
}
}