Самый большой линейный размер 2-й набор точек

Проблема возникла из-за того, что я генерировал токен CSRF после выполнения запроса. Это привело к тому, что токен сгенерировался дважды (я обнаружил, что он сбрасывает вещи в CsrfTokenManager).

Это работает:

// generates the CSRF token
$csrfToken = $client->getContainer()->get('security.csrf.token_manager')->getToken('division_item');

$crawler = $client->request('POST', '/teachers/add');
11
задан Jason S 25 October 2009 в 14:10
поделиться

5 ответов

Простой способ состоит в том, чтобы сначала найти выпуклую оболочку точек, которые могут быть сделаны в O (n, регистрируют n), время во многих отношениях. [Мне нравится сканирование Graham (см. анимацию), но возрастающий алгоритм также популярен, как другие, хотя некоторые занимают больше времени.]

Затем можно найти самую дальнюю пару (диаметр) путем запуска с любых двух точек (скажите, что X и Y) на выпуклой оболочке, двигаясь по часовой стрелке y, пока это не является самым далеким от x, затем перемещаясь x, перемещаясь y снова, и т.д. Можно доказать, что эта целая вещь берет только O (n) (амортизируемое) время. Таким образом, это - O (n, регистрируются, n) +O (n) =O (n регистрируют n) всего, и возможно O (nh), если Вы используете обертывание подарка в качестве своего алгоритма выпуклой оболочки вместо этого. Эту идею называют, поворачивая кронциркуль, как Вы упомянули.

Вот код David Eppstein (вычислительный исследователь геометрии; см. также его Алгоритмы Python и Структуры данных для дальнейшего использования).

Все это не очень трудно кодировать (должны быть сто строк самое большее; меньше чем 50 в коде Python выше), но прежде чем Вы сделаете это - необходимо сначала рассмотреть, нужен ли Вам действительно он. Если, как Вы говорите, у Вас будут только "тысячи точек", то затем тривиальный O (n^2) алгоритм (который сравнивает всех пар) будет выполнен в меньше, чем секунда на любом разумном языке программирования. Даже с миллионом точек не должно требоваться больше чем часа.:-)

Необходимо выбрать самый простой алгоритм, который работает.

18
ответ дан 3 December 2019 в 05:14
поделиться

На этой странице:

это показывает, что можно определить максимальный диаметр выпуклого полигона в O (n). Я просто должен превратить свой набор точки в выпуклый полигон сначала (вероятно, использующий сканирование Graham).

Вот некоторый код C#, с которым я столкнулся для вычислений выпуклой оболочки:

2
ответ дан 3 December 2019 в 05:14
поделиться

Я портировал код Python к C#. Это, кажется, работает.

using System;  
using System.Collections.Generic;  
using System.Drawing;  

// Based on code here:  
//   http://code.activestate.com/recipes/117225/  
// Jared Updike ported it to C# 3 December 2008  

public class Convexhull  
{  
    // given a polygon formed by pts, return the subset of those points  
    // that form the convex hull of the polygon  
    // for integer Point structs, not float/PointF  
    public static Point[] ConvexHull(Point[] pts)  
    {  
        PointF[] mpts = FromPoints(pts);  
        PointF[] result = ConvexHull(mpts);  
        int n = result.Length;  
        Point[] ret = new Point[n];  
        for (int i = 0; i < n; i++)  
            ret[i] = new Point((int)result[i].X, (int)result[i].Y);  
        return ret;  
    }  

    // given a polygon formed by pts, return the subset of those points  
    // that form the convex hull of the polygon  
    public static PointF[] ConvexHull(PointF[] pts)  
    {  
        PointF[][] l_u = ConvexHull_LU(pts);  
        PointF[] lower = l_u[0];  
        PointF[] upper = l_u[1];  
        // Join the lower and upper hull  
        int nl = lower.Length;  
        int nu = upper.Length;  
        PointF[] result = new PointF[nl + nu];  
        for (int i = 0; i < nl; i++)  
            result[i] = lower[i];  
        for (int i = 0; i < nu; i++)  
            result[i + nl] = upper[i];  
        return result;  
    }  

    // returns the two points that form the diameter of the polygon formed by points pts  
    // takes and returns integer Point structs, not PointF  
    public static Point[] Diameter(Point[] pts)  
    {  
        PointF[] fpts = FromPoints(pts);  
        PointF[] maxPair = Diameter(fpts);  
        return new Point[] { new Point((int)maxPair[0].X, (int)maxPair[0].Y), new Point((int)maxPair[1].X, (int)maxPair[1].Y) };  
    }  

    // returns the two points that form the diameter of the polygon formed by points pts  
    public static PointF[] Diameter(PointF[] pts)  
    {  
        IEnumerable<Pair> pairs = RotatingCalipers(pts);  
        double max2 = Double.NegativeInfinity;  
        Pair maxPair = null;  
        foreach (Pair pair in pairs)  
        {  
            PointF p = pair.a;  
            PointF q = pair.b;  
            double dx = p.X - q.X;  
            double dy = p.Y - q.Y;  
            double dist2 = dx * dx + dy * dy;  
            if (dist2 > max2)  
            {  
                maxPair = pair;  
                max2 = dist2;  
            }  
        }  

        // return Math.Sqrt(max2);  
        return new PointF[] { maxPair.a, maxPair.b };  
    }  

    private static PointF[] FromPoints(Point[] pts)  
    {  
        int n = pts.Length;  
        PointF[] mpts = new PointF[n];  
        for (int i = 0; i < n; i++)  
            mpts[i] = new PointF(pts[i].X, pts[i].Y);  
        return mpts;  
    }  

    private static double Orientation(PointF p, PointF q, PointF r)  
    {  
        return (q.Y - p.Y) * (r.X - p.X) - (q.X - p.X) * (r.Y - p.Y);  
    }  

    private static void Pop<T>(List<T> l)  
    {  
        int n = l.Count;  
        l.RemoveAt(n - 1);  
    }  

    private static T At<T>(List<T> l, int index)  
    {  
        int n = l.Count;  
        if (index < 0)  
            return l[n + index];  
        return l[index];  
    }  

    private static PointF[][] ConvexHull_LU(PointF[] arr_pts)  
    {  
        List<PointF> u = new List<PointF>();  
        List<PointF> l = new List<PointF>();  
        List<PointF> pts = new List<PointF>(arr_pts.Length);  
        pts.AddRange(arr_pts);  
        pts.Sort(Compare);  
        foreach (PointF p in pts)  
        {  
            while (u.Count > 1 && Orientation(At(u, -2), At(u, -1), p) <= 0) Pop(u);  
            while (l.Count > 1 && Orientation(At(l, -2), At(l, -1), p) >= 0) Pop(l);  
            u.Add(p);  
            l.Add(p);  
        }  
        return new PointF[][] { l.ToArray(), u.ToArray() };  
    }  

    private class Pair  
    {  
        public PointF a, b;  
        public Pair(PointF a, PointF b)  
        {  
            this.a = a;  
            this.b = b;  
        }  
    }  

    private static IEnumerable<Pair> RotatingCalipers(PointF[] pts)  
    {  
        PointF[][] l_u = ConvexHull_LU(pts);  
        PointF[] lower = l_u[0];  
        PointF[] upper = l_u[1];  
        int i = 0;  
        int j = lower.Length - 1;  
        while (i < upper.Length - 1 || j > 0)  
        {  
            yield return new Pair(upper[i], lower[j]);  
            if (i == upper.Length - 1) j--;  
            else if (j == 0) i += 1;  
            else if ((upper[i + 1].Y - upper[i].Y) * (lower[j].X - lower[j - 1].X) >  
                (lower[j].Y - lower[j - 1].Y) * (upper[i + 1].X - upper[i].X))  
                i++;  
            else  
                j--;  
        }  
    }  

    private static int Compare(PointF a, PointF b)  
    {  
        if (a.X < b.X)  
        {  
            return -1;  
        }  
        else if (a.X == b.X)  
        {  
            if (a.Y < b.Y)  
                return -1;  
            else if (a.Y == b.Y)  
                return 0;  
        }  
        return 1;  
    }  
}  
2
ответ дан 3 December 2019 в 05:14
поделиться

Вы могли, возможно, нарисовать круг, который был больше, чем полигон, и медленно уменьшайте его, проверяя, пересек ли youve какие-либо точки уже. Затем Ваш диаметр является числом, которое Вы ищете. Не уверенный, если это - хороший метод, это звучит где-нибудь между O (n) и O (n^2)

0
ответ дан 3 December 2019 в 05:14
поделиться

Мое неподготовленное решение состоит в том, чтобы попробовать двоичный подход разделения, где Вы чертите линию somwwhere в середине и проверяете расстояния всех точек с середины той строки. Это предоставило бы Вам 2, По-видимому, Очень Далеких точки. Затем проверьте расстояние тех двух и повторите вышеупомянутую проверку расстояния. Повторите этот процесс некоторое время.

Мой пищеварительный тракт говорит, что это - журнал n n эвристика, которая получит Вас Достаточно близкий.

0
ответ дан 3 December 2019 в 05:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: