给定距离d
(从0
到d
)和2点s
和e
之间,其中无法放置任何积分(放置s
和e
上的点数没问题,不允许在它们之间放置点数。)
放置n
点,使每个点之间的距离尽可能大(尽可能均匀地分布)。
输出2点之间的最小距离。
图形表示,将n
点放在黑线上(它是一条1维线),以便每两个点之间的最小距离尽可能大(绝对误差最高为{允许{1}}。
示例:
我的方法:
我尝试单独查看间隔,在第一和第二个间隔(10^(-4)
到lengthOfInterval
和{{分配点(理想分布n
/ 0
) 1}}到s
)并检查点数总和为e
的所有分布,我将存储一个(分布,最大最小距离)对并选择具有最大最小距离的对。我不知道如何使用d
容差(这部分甚至在代码中看起来怎么样?)并且不确定我的方法是否正确。欢迎提出任何建议。
我坚持这个问题:/
答案 0 :(得分:1)
您可以使用二进制搜索覆盖点之间可能的间隙大小(从0
到d
),以收敛到最大的最小间隙大小。
要确定任何给定间隙大小的可行性,您基本上会尝试从左侧和右侧放置点,看看中间的间隙是否足够大:
s
左侧可以放置的点数(s/gapSize + 1
)。e
的右侧放置多少个点
(n - points on left
)。[e, d]
以及每边之间是否至少有gap size
差异。此代码:(注意我使用的是间隙数而不是点数,这比点数少1,因为它会导致更简单的代码)
double high = d, low = 0, epsilon = 0.000001;
while (low + epsilon < high)
{
double mid = (low + high)/2;
int gapsOnLeft = (int)(s/mid); // gaps = points - 1
if (gapsOnLeft + 1 > n)
gapsOnLeft = n - 1;
int gapsOnRight = n - gapsOnLeft - 2; // will be -1 when there's no point on the right
double leftOffset = mid*gapsOnLeft;
// can be > d with no point on the right, which makes the below check work correctly
double rightOffset = d - mid*gapsOnRight;
if (leftOffset + mid <= rightOffset && rightOffset >= e)
low = mid;
else
high = mid;
}
System.out.println(low);
时间复杂度为O(log d)
。
你的方法的问题在于很难弄清楚点之间的间隙有多大,所以你不知道在(s, e)
的任何一侧应该有多少点。最终得到一个最佳解决方案,并在s
和e
非常接近并且它们相距很远时正确处理这两种情况。
答案 1 :(得分:0)
二进制搜索
如果给出任意对l
的最小间隔距离b / w,则很容易找到可以放置的点数。
如果l = d,那么最多只能放置2个点。
..
......
....
所以只需在l上进行二元搜索。
粗略的实现是这样的。
low,high=0.00001,d
while(high-low>eps):
m = (low+high)/2
if((no. of points placed s.t any pair is at most m units away) >=n):
low=mid
else:
high=mid
答案 2 :(得分:0)
TL; DR:您的方法并不总是有效(并且您没有尽可能快地执行此操作)查看有效的方法的第3个要点(并使用给定的方法) 10 ^( - 4)。)
如果[s, e]
很小并且放置得很好,那么最佳值只是在整个细分上均匀分布,最佳值现在为d/(n-1)
。但是,您必须检查s
和e
之间没有任何元素。
如果s
和e
足够#34;您的方法有效。&#34;
您可以通过查看两个细分受众群之间的最佳分割O(1)
来快速完成,而不是您的建议:如果您放置n1
(1<=n1<=n-1
)元素在左侧,您希望最大化min(s/(n1-1), (d-e)/(n-n1-1))
(其中一个数量可能为+infinity
,但另一个数量不是s/(x-1) = (d-e)/(n-x-1)
。 x
获得该函数的最大值,只计算n1
的对应值,其最低值或最高值是best = min(s/(n1-1), (d-e)/(n-n1-1))
的最佳值。获得的距离为n1
然后您将0
点放在左侧,从best
开始,以距离n-n1
分隔,并在右侧开始d
,开始在best
左转,由sp
分隔。
如果左边的最后一点和右边的第一个点之间的距离小于最佳点,那么你有问题,这种方法不起作用。
sp
,尝试在0开始的行上分配点,间隔(last on the left + sp)
,尽可能多地保留在s以下。在高于e及sp
以上时,在右侧执行相同操作。如果您已成功放置至少n个点,则sp
太小。否则,它太大了。 因此,您可以使用二分搜索来找到最佳mid
,如下所示:从sp开始,可能在[max(s,d-e)/(n-1),d /(n-1)]中。在每个步骤中,获取可能的细分[x, y]
的中间mid
。检查实际最佳值是高于还是低于[mid, y]
。根据您的情况,请在[x, mid]
或y-x < 10^(-4)
中查找最佳值。停止iff persist.demo.hdmirotation=portrait
ro.sf.hwrotation=270 (I have tried 90 too)
windowsmgr.support_rotation_270=true
。
实际上也可以通过这种方法找到前两种情况,因此您不需要实现它们,除非您希望在可能的情况下获得精确的最佳值(即在前两种情况下)。
答案 3 :(得分:0)
这非常棘手,除了简单的情况(没有点落在差距中):
double dMin = d / (n - 1.0);
if (Math.ceil(e / dMin - 1) * dMin <= s)
return dMin;
让我们继续处理边缘情况,在一侧放置一个点,在另一侧放置其余点:
dMin = Math.min((d - e) / (n - 2.0), e); // one point at 0
double dm = Math.min(s / (n - 2.0), d - s); // one point at d
if (dm > dMin) // 2nd configuration was better
dMin = dm;
最后两边都有两点或多点:
// left : right = (x - 1) : (n - x - 1)
// left * n - left * x - left = right * x - right
// x * (left + right) = left * n - left + right
// x = (left * n - left + right) / (left + right) = (left * n) / (left + right) - 1
int x = s * n / (d - e + s) - 1;
if (x < 2)
x = 2;
for (int y = x; y <= x + 2 && y < n - 1; y++) {
double dLeft = s / (y - 1.0);
double dRight = (d - e) / (n - y - 1.0);
dm = Math.min(dLeft, dRight);
if (dm > e - s) { // dm bigger than gap
if (dLeft > dRight)
dLeft = e / ((double) y);
else
dRight = (d - s) / ((double) n - y);
dm = Math.min(dLeft, dRight);
}
if (dm > dMin)
dMin = dm;
}
这将是 O(1)空间和时间,但如果检查所有情况,我不是100%正面。如果有效,请告诉我。 针对所有测试用例进行测试。以上适用于n >= 2
,如果n等于2,它将被第一次检查捕获。