Java 如何以低成本处理多个范围(找到最大值)

Java 如何以低成本处理多个范围(找到最大值),java,algorithm,performance,range,maximize,Java,Algorithm,Performance,Range,Maximize,我有很多范围,每个范围都有一个重量。总范围内的每一个点都由该点所属的所有范围的权重之和来评分。我希望能够便宜地找到积分的总价值,并希望能够找到最大值。理想情况下,它还能够找到一组(等距)间距点的最大值 不幸的是,我受到性能的严重限制,正在努力找到一个好的算法 我能找到的唯一两个体面的解决方案是: -通过对一组点进行采样来强制执行。对于每个:检查每个范围是否合适,找到总值,然后检查是否比目前为止最好的更好。通过获取范围的边界可以找到合适的点样本。 -创建一组桶。迭代所有范围,为该范围内的所有存储桶

我有很多范围,每个范围都有一个重量。总范围内的每一个点都由该点所属的所有范围的权重之和来评分。我希望能够便宜地找到积分的总价值,并希望能够找到最大值。理想情况下,它还能够找到一组(等距)间距点的最大值

不幸的是,我受到性能的严重限制,正在努力找到一个好的算法

我能找到的唯一两个体面的解决方案是: -通过对一组点进行采样来强制执行。对于每个:检查每个范围是否合适,找到总值,然后检查是否比目前为止最好的更好。通过获取范围的边界可以找到合适的点样本。 -创建一组桶。迭代所有范围,为该范围内的所有存储桶添加一个值。然后遍历所有bucket以找到最佳的bucket

两者都不够快(它们已经过测试),后者不是连续的,因此存在准确性问题

只要性能更好,我可以接受稍微不准确的回答。 给我的特殊情况增加一点额外复杂性的是,我实际上是在处理角度,所以环境是模块化的。这些范围无法排序,我需要确保从340度到20度的范围包含350度和10度的点。 我正在处理的角度范围不能超过180度,而且很少超过90度。 范围的数量通常不是很高(1-30),但我需要经常进行这种计算

如果重要的话,语言是Java。

列出角度间隔(数组)。如果间隔完成值小于开始值(20

在这里,我应该更好地使用术语“边界”,而不是术语“边”,因为它指的是区间边界

    import java.util.ArrayList;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

public class Main {

    ArrayList<Interval> intervals;

    public static void main(String args[]) {

        Main main = new Main();

        main.intervals = new ArrayList<Interval>();
        Interval i1 = new Interval(10, 30, 1);
        Interval i2= new Interval(20, 40, 1);
        Interval i3= new Interval(50, 60, 1);
        Interval i4= new Interval(0, 70, 1);

        main.intervals.add(i1);
        main.intervals.add(i2);
        main.intervals.add(i3);
        main.intervals.add(i4);

        Interval winningInterval = main.processIntervals(main.intervals);
        System.out.println("winning interval="+winningInterval);



    }


    public Interval processIntervals(ArrayList<Interval> intervals)
    {
        SortedSet<Integer> intervalEdges = new TreeSet<Integer>();

        for(int i = 0;i<intervals.size();i++)
        {
            Interval currentInterval = intervals.get(i);
            intervalEdges.add(currentInterval.a);
            intervalEdges.add(currentInterval.b);
        }

        System.out.println(intervalEdges);

        //edges stores the same data as intervalEdges, but for convenience, it is a list
        ArrayList<Integer> edges = new ArrayList<Integer>(intervalEdges);

        ArrayList<Interval> intersectionIntervals = new ArrayList<Interval>();

        for(int i=0; i<edges.size()-1;i++)
        {
            Interval newInterval = new Interval(edges.get(i), edges.get(i+1), 0);

            int score = 0; //the sum of the values of the overlapping intervals
            for(int j=0; j<intervals.size();j++)
            {
                if(newInterval.isIncludedInInterval(intervals.get(j)))
                    score = score+ intervals.get(j).val;
            }

            newInterval.val = score;
            intersectionIntervals.add(newInterval);
        }

        System.out.println(intersectionIntervals);

        int maxValue=0; //the maximum value of an interval
        Interval x = new Interval(-1,-1,0);//that interval with the maximum value
        for(int i=0; i<intersectionIntervals.size();i++)
            {
            if(intersectionIntervals.get(i).val > maxValue)
            {
                maxValue=intersectionIntervals.get(i).val;
                x=intersectionIntervals.get(i);
            }
            }


        return x;
    }



}


class Interval
{
    public int a, b, val;

    public Interval(int a, int b, int val) {
        super();
        this.a = a;
        this.b = b;
        this.val = val;

    }

    @Override
    public String toString() {
        return "Interval [a=" + a + ", b=" + b + ", val=" + val + "]";
    }

    boolean isIncludedInInterval(Interval y)
    {
        //returns true if current interval is included in interval y
        return this.a>=y.a && this.b<= y.b;
    }
}

这解决了间隔是直线间隔而不是角度间隔的问题。我会根据x=x+360这一事实进行修改。

你能更准确地描述这个问题吗?你能给出一个例子而不是详细的解释吗?我需要找到一个最佳的射击角度。我的游戏中有一些对象是w从我的位置到角度方向的假想线需要与之相交的世界,因为我想击中或阻止击中它们。某些对象比其他对象更值钱(因此权重)。每个物体都可以表示为最左和最右相交的角度,这些是范围。在某些情况下,我需要一组线与尽可能多的线相交,想象一下猎枪式射击,几颗子弹以不同的、可预测的角度飞走。这似乎可行!谢谢!至少在O表示法的术语这应该更低。我必须尝试一下,因为在实践中,排序可能会和其他方法一样昂贵。只需复制穿过0角度的范围,并在0以下开始我的值跟踪可能会起作用(尽管在超过0之前无法获得结果)。排序是O(nlogn)。实际上,您需要将列表的一部分复制到最后一次完成时间(例如,最后一次360+70限制为70)。但是,这种复制只会使事情变得更复杂。这会怎么样?1.通过迭代原始范围一次来确定0度的值。2.将所有角度视为间隔
(0,360)中的数字
.3.对于每个开始添加
(x,+重量)
,对于每个结束添加
(x,-重量)
,并像往常一样对该列表进行排序。忽略循环。
    [0, 10, 20, 30, 40, 50, 60, 70]
[Interval [a=0, b=10, val=1], Interval [a=10, b=20, val=2], Interval [a=20, b=30, val=3], Interval [a=30, b=40, val=2], Interval [a=40, b=50, val=1], Interval [a=50, b=60, val=2], Interval [a=60, b=70, val=1]]
winning interval=Interval [a=20, b=30, val=3]