礼品包装算法 java(gift wrapping)

礼品包装算法 java(gift wrapping)

convexHull(参考的博客)

这个题有很多解法,我采用的是gift wrapping算法.

思路:

1.找一个极点(左上角,左下角,右上角或者右下角,我找得是左上角)

2.遍历所有点,找出和极点偏转角度最小的(顺时针).

3.将当前点作为下一个极点,继续找点.

4.直到找到第一个极点,算法结束.
public static Set<Point> convexHull(Set<Point> points) {
       if(points.size()>3)
       {
           Set<Point> convexHull = new HashSet<Point>();
//           左上方的点必然在凸包中(左上方点的定义,首先若x最小,那么它为最左边的点,若有两个点的x同为最小,那么y值越小的点,就是最左边的点)
           Point p0 = new Point(Double.MAX_VALUE, Double.MAX_VALUE);
           Map<Point,Boolean>isinsert=new HashMap<>();
           for (Point item : points) {
               isinsert.put(item,false);
               if (item.x() < p0.x() || (item.x() == p0.x() && item.y() < p0.y()))
                   p0 = item;
           }


           Point nowPoint = p0, tempPoint = p0;
           double nowAngle = 0;
           double minAngle = 360;
           double tempAngle = 0;
           double distance;
           double maxdistance = -1;
           do {
               if(nowPoint!=p0){
                   isinsert.put(nowPoint,true);
               }
               convexHull.add(nowPoint);
               for (Point item : points) {
                   if ((!convexHull.contains(item)||(item==p0&&ischanged(isinsert)))) {
                       tempAngle = calculateBearingToPoint11(nowAngle, nowPoint.x(), nowPoint.y(), item.x(), item.y());
                       distance = distance(item,nowPoint);
//                       顺时针找下一个在凸包中的点,如果偏转角度相同,取距离更远的点(点的优先级1.偏转角度,2.点到上一个点的距离)
                       if (tempAngle < minAngle || ((tempAngle == minAngle) && (distance > maxdistance))) {
                           minAngle = tempAngle;
                           tempPoint = item;
                           maxdistance = distance;

                       }
                   }
               }
               minAngle = 360;
               nowAngle = 0;
               nowPoint = tempPoint;
           } while (nowPoint!=p0);
           return convexHull;
       }
       else{
           return points;
       }



    }

    public static boolean ischanged(Map<Point,Boolean>isinsert){
        for(Map.Entry<Point, Boolean> entry : isinsert.entrySet()){
            if(entry.getValue()==true){
                return true;
            }
        }
        return false;
    }

private static double distance(Point p1, Point p2) {
        return (p1.x() - p2.x()) * (p1.x() - p2.x()) + (p1.y() - p2.y()) * (p1.y() - p2.y());
    }

public static double calculateBearingToPoint11(double currentBearing, double currentX, double currentY,
                                                   double targetX, double targetY) {
        double angle = Math.toDegrees(Math.atan2(targetX - currentX, targetY - currentY));
        double turnAngle = angle - currentBearing;
        if (turnAngle < 0)
            turnAngle += 360;
        return  turnAngle;
    }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值