C# 从凸包中删除点(Deleting points from Convex Hull)

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

给定一个固定的点集,我们需要找到该点集的凸包。此外,我们还需要找到从该点集中移除一个点后得到的凸包。

例子:

初始点集:(-2, 8) (-1, 2) (0, 1) (1, 0)

(-3, 0) (-1, -9) (2, -6) (3, 0)

(5, 3) (2, 5)

初始凸包:(-2, 8) (-3, 0) (-1, -9) (2, -6)

(5, 3)

从点集中移除的点:(-2, 8)

最终凸包:(2, 5) (-3, 0) (-1, -9) (2, -6) (5, 3)

前提条件:凸包(简单的分治算法)

JavaScript 利用分治算法求凸包:JavaScript 利用分治算法求凸包(Convex Hull using Divide and Conquer Algorithm)-CSDN博客

C# 利用分治算法求凸包:C# 利用分治算法求凸包(Convex Hull using Divide and Conquer Algorithm)-CSDN博客

Python 利用分治算法求凸包:Python 利用分治算法求凸包(Convex Hull using Divide and Conquer Algorithm)-CSDN博客

Java 利用分治算法求凸包:Java 利用分治算法求凸包(Convex Hull using Divide and Conquer Algorithm)-CSDN博客

C++ 利用分治算法求凸包:C++ 利用分治算法求凸包(Convex Hull using Divide and Conquer Algorithm)-CSDN博客

解决上述问题的算法非常简单。我们只需检查要移除的点是否属于凸包。如果是,则必须从初始集合中移除该点,然后重新构建凸包(参见上面凸包(分治))。

如果不是这样,那么我们已经有了解决方案(凸包不会改变)。

using System;

using System.Collections.Generic;

class Pair : IComparable<Pair>

{

public int First { get; set; }

public int Second { get; set; }

public Pair(int first, int second)

{

First = first;

Second = second;

}

public int CompareTo(Pair other)

{

if (First != other.First)

{

return First - other.First;

}

return Second - other.Second;

}

}

class ConvexHull

{

// Stores the center of the polygon (made global because it is used in the Compare function)

static Pair mid = new Pair(0, 0);

// Determines the quadrant of a point (used in Compare())

static int Quad(Pair p)

{

if (p.First >= 0 && p.Second >= 0)

{

return 1;

}

if (p.First <= 0 && p.Second >= 0)

{

return 2;

}

if (p.First <= 0 && p.Second <= 0)

{

return 3;

}

return 4;

}

// Checks whether the line is crossing the polygon

static int Orientation(Pair a, Pair b, Pair c)

{

int res = (b.Second - a.Second) * (c.First - b.First) - (c.Second - b.Second) * (b.First - a.First);

if (res == 0)

{

return 0;

}

if (res > 0)

{

return 1;

}

return -1;

}

// Compare function for sorting

static int Compare(Pair p1, Pair p2)

{

Pair p = new Pair(p1.First - mid.First, p1.Second - mid.Second);

Pair q = new Pair(p2.First - mid.First, p2.Second - mid.Second);

int one = Quad(p);

int two = Quad(q);

if (one != two)

{

return one - two;

}

return Math.Sign(p.Second * q.First - q.Second * p.First);

}

// Finds upper tangent of two polygons 'a' and 'b' represented as two lists.

static List<Pair> Merger(List<Pair> a, List<Pair> b)

{

int n1 = a.Count;

int n2 = b.Count;

int ia = 0, ib = 0;

for (int i = 1; i < n1; i++)

{

if (ai.First > aia.First)

{

ia = i;

}

}

for (int i = 1; i < n2; i++)

{

if (bi.First < bib.First)

{

ib = i;

}

}

int inda = ia, indb = ib;

bool done = false;

while (!done)

{

done = true;

while (Orientation(bindb, ainda, a(inda + 1) % n1) >= 0)

{

inda = (inda + 1) % n1;

}

while (Orientation(ainda, bindb, b(n2 + indb - 1) % n2) <= 0)

{

indb = (n2 + indb - 1) % n2;

done = false;

}

}

int uppera = inda, upperb = indb;

inda = ia;

indb = ib;

done = false;

while (!done)

{

done = true;

while (Orientation(ainda, bindb, b(indb + 1) % n2) >= 0)

{

indb = (indb + 1) % n2;

}

while (Orientation(bindb, ainda, a(n1 + inda - 1) % n1) <= 0)

{

inda = (n1 + inda - 1) % n1;

done = false;

}

}

int lowera = inda, lowerb = indb;

List<Pair> ret = new List<Pair>();

int ind = uppera;

ret.Add(auppera);

while (ind != lowera)

{

ind = (ind + 1) % n1;

ret.Add(aind);

}

ind = lowerb;

ret.Add(blowerb);

while (ind != upperb)

{

ind = (ind + 1) % n2;

ret.Add(bind);

}

return ret;

}

// Brute force algorithm to find convex hull for a set of less than 6 points

static List<Pair> BruteHull(List<Pair> a)

{

HashSet<Pair> s = new HashSet<Pair>();

for (int i = 0; i < a.Count; i++)

{

for (int j = i + 1; j < a.Count; j++)

{

int x1 = ai.First, x2 = aj.First;

int y1 = ai.Second, y2 = aj.Second;

int a1 = y1 - y2;

int b1 = x2 - x1;

int c1 = x1 * y2 - y1 * x2;

int pos = 0, neg = 0;

foreach (var k in a)

{

if (a1 * k.First + b1 * k.Second + c1 <= 0)

{

neg++;

}

if (a1 * k.First + b1 * k.Second + c1 >= 0)

{

pos++;

}

}

if (pos == a.Count || neg == a.Count)

{

s.Add(ai);

s.Add(aj);

}

}

}

List<Pair> ret = new List<Pair>(s);

mid = new Pair(0, 0);

int n = ret.Count;

for (int i = 0; i < n; i++)

{

mid.First += reti.First;

mid.Second += reti.Second;

reti.First *= n;

reti.Second *= n;

}

ret.Sort(Compare);

for (int i = 0; i < n; i++)

{

reti.First /= n;

reti.Second /= n;

}

return ret;

}

// Returns the convex hull for the given set of points

static List<Pair> FindHull(List<Pair> a)

{

if (a.Count <= 5)

{

return BruteHull(a);

}

List<Pair> left = new List<Pair>();

List<Pair> right = new List<Pair>();

for (int i = 0; i < a.Count / 2; i++)

{

left.Add(ai);

}

for (int i = a.Count / 2; i < a.Count; i++)

{

right.Add(ai);

}

List<Pair> leftHull = FindHull(left);

List<Pair> rightHull = FindHull(right);

return Merger(leftHull, rightHull);

}

// Returns the convex hull for the given set of points after removing a point p.

static List<Pair> RemovePoint(List<Pair> a, List<Pair> hull, Pair p)

{

bool found = false;

for (int i = 0; i < hull.Count && !found; i++)

{

if (hulli.First == p.First && hulli.Second == p.Second)

{

found = true;

}

}

if (!found)

{

return hull;

}

for (int i = 0; i < a.Count; i++)

{

if (ai.First == p.First && ai.Second == p.Second)

{

a.RemoveAt(i);

break;

}

}

a.Sort(Compare);

return FindHull(a);

}

// Driver code

public static void Main(string\[\] args)

{

List<Pair> a = new List<Pair>();

a.Add(new Pair(0, 0));

a.Add(new Pair(1, -4));

a.Add(new Pair(-1, -5));

a.Add(new Pair(-5, -3));

a.Add(new Pair(-3, -1));

a.Add(new Pair(-1, -3));

a.Add(new Pair(-2, -2));

a.Add(new Pair(-1, -1));

a.Add(new Pair(-2, -1));

a.Add(new Pair(-1, 1));

// Sorting the set of points according to the x-coordinate

a.Sort();

List<Pair> hull = FindHull(a);

Console.WriteLine("Convex hull:");

foreach (var e in hull)

{

Console.WriteLine($"{e.First} {e.Second}");

}

Pair p = new Pair(-5, -3);

hull = RemovePoint(a, hull, p);

Console.WriteLine("\nModified Convex Hull:");

foreach (var e in hull)

{

Console.WriteLine($"{e.First} {e.Second}");

}

}

}

输出:

凸包(convex hull):

-3 0

-1 -9

2 -6

5 3

2 5

**时间复杂度:**很容易看出,每次查询所花费的最大时间是构建凸包所需的时间,即 O(n*logn)。因此,总复杂度为 O(q*n*logn),其中 q 为要删除的点数。

辅助空间: O(n),因为占用了 n 个额外的空间。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
cts6181 小时前
Python全栈claude.md文档
开发语言·python
忘路之远近i2 小时前
受够阿里云自带终端后,我用 Cursor + grill-me 做了个运维面板
服务器·开发语言·人工智能·python·阿里云·云计算
Tim_102 小时前
【C++】020、野指针&悬空指针
java·开发语言
吃好睡好便好2 小时前
MATLAB中图像格式的转换
开发语言·图像处理·学习·计算机视觉·matlab
爱喝水的鱼丶2 小时前
SAP-ABAP:SELECT大数据量查询性能调优——避免嵌套循环、减少数据库交互的核心方案
开发语言·数据库·sql·性能优化·sap·abap·erp
Dxy12393102162 小时前
Python 实现POST上行压缩上传可用HTTP库汇总
开发语言·python·http
czhc11400756632 小时前
7.28 从“图形状态切换“理解 Parse 与状态驱动模式
c#
郝学胜-神的一滴2 小时前
Python 高级编程 026:序列内核深剖
开发语言·python·程序人生·软件工程