Algorithm 如何找到包含所有点或与y=x轴对称的点的最小矩形?

Algorithm 如何找到包含所有点或与y=x轴对称的点的最小矩形?,algorithm,optimization,dynamic-programming,mathematical-optimization,Algorithm,Optimization,Dynamic Programming,Mathematical Optimization,我有一组点(x,y)。如何找到包含这些点或与y=x轴对称的点的最小矩形(边垂直于坐标系的轴)?并非所有的点都必须同时是镜像,因此有可能与原始点有一些法线和一些对称点。您可以使用蛮力O(n*2^n)方法解决此问题:将点定义为一些类/结构,除了点的(x,y)坐标,还保存布尔镜像状态。对于n点数,循环检查这组点数的所有2^n可能的状态集。对于每组状态,计算边界矩形的周长(2x+2y) 以下是在Swift中实施的此解决方案。如果你选择使用这种暴力手段,希望你能把它翻译成你选择的语言 点容器和帮助功能:

我有一组点(x,y)。如何找到包含这些点或与y=x轴对称的点的最小矩形(边垂直于坐标系的轴)?并非所有的点都必须同时是镜像,因此有可能与原始点有一些法线和一些对称点。

您可以使用蛮力
O(n*2^n)
方法解决此问题:将点定义为一些类/结构,除了点的
(x,y)
坐标,还保存布尔
镜像状态。对于
n
点数,循环检查这组点数的所有
2^n
可能的状态集。对于每组状态,计算边界矩形的周长(
2x+2y

以下是在Swift中实施的此解决方案。如果你选择使用这种暴力手段,希望你能把它翻译成你选择的语言


点容器和帮助功能:

struct Point {
    private var xOrig : Double
    private var yOrig : Double
    private var mirrored = false
    var x : Double { return mirrored ? yOrig : xOrig }
    var y : Double { return mirrored ? xOrig : yOrig }

    init(_ x: Double, _ y: Double) {
        xOrig = x
        yOrig = y
    }

    mutating func setState(state: Bool) {
        mirrored = state
    }
}

func boundingBoxCircumference(points: [Point]) -> Double {
    let xMax = points.maxElement { $0.x < $1.x }?.x ?? 0.0
    let xMin = points.minElement { $0.x < $1.x }?.x ?? 0.0
    let yMax = points.maxElement { $0.y < $1.y }?.y ?? 0.0
    let yMin = points.minElement { $0.y < $1.y }?.y ?? 0.0

    return 2*((xMax - xMin) + (yMax - yMin))
}

func setMirroredStates(inout points: [Point], states: [Bool]) {
    for i in 0..<points.count {
        points[i].setState(states[i])
    }
}
结构点{
私家车:双人
二等兵约里格:双人
私有变量镜像=false
var x:Double{返回镜像?yOrig:xOrig}
变量y:Double{返回镜像?xOrig:yOrig}
初始化(x:Double,y:Double){
xOrig=x
yOrig=y
}
变异函数设置状态(状态:Bool){
镜像=状态
}
}
func BoundingBoxPercentage(点:[点])->双精度{
设xMax=points.maxElement{$0.x<$1.x}?.x??0.0
设xMin=points.minElement{$0.x<$1.x}?.x??0.0
设yMax=points.maxElement{$0.y<$1.y}?.y??0.0
设yMin=points.minElement{$0.y<$1.y}?.y??0.0
返回2*((xMax-xMin)+(yMax-yMin))
}
func setMirroredStates(输入输出点:[点],状态:[Bool]){
对于我来说,0..Double{
var smallestBox=Double.infinity
因为我在0..0{
binString=“.stringByPaddingToLength(a,带字符串:“0”,起始索引:0)+binString
}
设pointStates=Array(binString.characters).map{String($0)==“1”}
setMirroredStates(&points,states:pointStates)
}
返回最小箱
}
var myPoints:[点]=[点(1,2),点(-4,3),点(7,-5),点(5,4),点(-5,-1)]
打印(FindSalestBox(myPoints))//34

您基本上是在问如何计算二维边界矩形吗?只需在集合中的每个点上循环,并获得每个组件的最小值和最大值,就可以得到一个边界矩形;他要求使用轴对齐的boundingrect,但可以选择将集合中任意多个点替换为镜像对应点。这就是挑战,所以这不是挑战。如果对称性是轴对称或两个象限,如果是点对称,则通过镜像所有点,使它们分布在一个象限上,可以很容易地生成最小的矩形。@Paul I也有类似的怀疑,但对此毫无把握。但如果是这样的话,就把它作为一个答案发布吧!最小x*y还是最小x+y?谢谢你的代码,但不幸的是我知道暴力解决方案。我正在寻找一个更好的解决方案,因为0(n*2^n)太多了。@WojtekPrzechodzeń我明白了,也许其他人可以想出一些办法。
func findSmallestBox(var points: [Point]) -> Double {
    var smallestBox = Double.infinity
    for i in 0..<Int(pow(2,Double(points.count))) {
        smallestBox = min(smallestBox, boundingBoxCircumference(points))

        var binString = String(i, radix: 2)
        if let a = Optional(points.count - binString.characters.count) where a > 0 {
            binString = "".stringByPaddingToLength(a, withString: "0", startingAtIndex: 0) + binString
        }
        let pointStates = Array(binString.characters).map { String($0) == "1" }

        setMirroredStates(&points, states: pointStates)
    }
    return smallestBox
}

var myPoints : [Point] = [Point(1,2), Point(-4,3), Point(7,-5), Point(5,4), Point(-5, -1)]
print(findSmallestBox(myPoints)) // 34