尋找凸包(Graham掃描法)
題意描述:
對任意給定的平面上的點集,求最小凸多邊形使得點集中的點要麼在凸多邊形的邊上,要麼在凸多邊形的內部。
Graham演算法描述:
- 在所有的點中找到一點p0,使得p0的縱座標值最小,在有多個最小縱座標的情況下,找橫座標最小的那一個。
- 將所有的點< p0, p1,…pn> 按規則(相對於p0的幅角從小到大,也就是繞p0逆時針,如有幅角相等的點,只保留離p0最遠的那個,其他的刪除)排序。
- 如果所剩的頂點數m小於3,不能構成凸包,retrun false;
- 將前三個點如空棧S。
- for i = 3 to m
- while point next-to-top(S), point top(S), point i
- pop(S)
- push(point i, S)
- return S
棧S中的點即為構成凸包的點。
圖解:
example
輸入
8
A -1 2
B 1 1
C 3 4
D 2 2
E 2 5
F 3 2
G 2 6
H 3 3
輸出:
B 1 1
F 3 2
C 3 4
G 2 6
A -1 2
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#define INF 0x3f3f3f3f
#define MAXN 50
using namespace std;
struct point { char name; double x, y; };
vector<point> res; //陣列模擬棧
vector<point> points; //點集
point p0; //y最小的情況下, x最小的點
double dis(point p1, point p2) {
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
bool cmp(const point p1, const point p2){ //atan2(y, x)返回向量xy和x軸正方向的夾角(-180到180)
if (atan2(p1.y - p0.y, p1.x - p0.x) == atan2(p2.y - p0.y, p2.x - p0.x))
return dis(p0, p1) < dis(p0, p2);
return atan2(p1.y - p0.y, p1.x - p0.x) < atan2(p2.y - p0.y, p2.x - p0.x);
}
bool istureleft(const point p0, const point p1, const point p2) { //p2是否相對於p1左轉
double angle1 = atan2(p1.y - p0.y, p1.x - p0.x);
double angle2 = atan2(p2.y - p0.y, p2.x - p0.x);
if (angle1 < 0) angle1 += 2 * 3.1416;
if (angle2 < 0) angle2 += 2 * 3.1416;
return angle1 - angle2 < 0;
}
int main() {
char c;
double x, y;
size_t i, n, index;
while (cin >> n) {
res.clear(); //清空棧
p0 = { ' ', INF, INF }; //初始化p0
points.clear();
for (i = 0; i < n; ++i) {
cin >> c >> x >> y;
points.push_back(point{ c, x, y });
if (y < p0.y || y == p0.y && x < p0.x) { index = i, p0 = { c, x, y }; } //更新p0
}
sort(points.begin(), points.end(), cmp);
index = 0;
res.push_back(points[index++]); //前三個點進棧
res.push_back(points[index++]);
res.push_back(points[index++]);
for (; index < n; index++) {//對後邊的每一個點
while (!istureleft(*(res.end() - 2), *(res.end() - 1), points[index]))
res.erase(res.end() - 1);
res.push_back(points[index]);
}
for (i = 0; i < res.size(); ++i)
cout << res[i].name << " " << res[i].x << " " << res[i].y << endl;
}
return 0;
}
相關推薦
尋找凸包(Graham掃描法)
題意描述: 對任意給定的平面上的點集,求最小凸多邊形使得點集中的點要麼在凸多邊形的邊上,要麼在凸多邊形的內部。 Graham演算法描述: 在所有的點中找到一點p0,使得p0的縱座標值最小,在有多個最小縱座標的情況下,找橫座標最小的那一個。 將所有的點
matlab練習程式(尋找凸包,Graham掃描法)
我不太清楚這個凸包在影象處理中到底會怎樣的運用,因為這個好像更多的是計算幾何或是圖形學裡面的東西。不過作為一個演算法,我感覺還是有必要研究一下的。我主要的參考資料是《演算法導論》的33.3和這個部落格。 程式碼在這裡,我只寫了主要過程,過分細節的判斷就省略了。這裡是逆時針尋找: main.m c
凸包演算法(Graham掃描法)
目錄 一、概念 二、演算法步驟 三、程式碼實現 轉自:https://www.cnblogs.com/aiguona/p/7232243.html 一、概念 凸包(Convex Hull)是一個計算幾何(圖形學)中的概念。 在一個實數向量空間V中,對於給定集合X,所有
淺談凸包及Graham掃描法
凸包是計算幾何中的一個基本概念。在競賽中,很少單獨考察凸包,但求凸包是很多題目求解的一個關鍵性步驟。 1)凸包的性質 給定一個點集,凸包是能夠包圍所有點的最小凸多邊形。”凸包邊上的點,稱為凸包點,其餘點稱為凸包內點“(引自何援軍著《幾何計算
凸包問題—Graham掃描法
#include<iostream> #include<cmath> #include<algorithm> using namespace std; struct point { long long x; long l
凸包模板(分治 or Graham掃描法)
問題概述:空間上有很多點,現在要用一個凸多邊形將所有點全部包住,求哪些點在這個凸多邊形上 輸入樣例: 對應輸出:
1015 - 計算幾何之Graham掃描法求凸包 - Cows(POJ 3348)
傳送門 題意 給你一堆點,求這些點的凸包,並求出面積 分析 很久之前就做過的一道題了,還記得那是凱爺(凱爺好厲害好厲害的)講的,是Jarris步進法:按照橫縱座標對所有的點進行排序(橫座標優先) 然後就是和Graham類似的方法了,邊掃描邊
凸包(Convex Hull)構造演算法——Graham掃描法
凸包(Convex Hull) 在圖形學中,凸包是一個非常重要的概念。簡明的說,在平面中給出N個點,找出一個由其中某些點作為頂點組成的凸多邊形,恰好能圍住所有的N個點。 這十分像是在一塊木板上釘了N個釘子,然後用一根繃緊的橡皮筋它們都圈起來,這根橡皮筋的形狀就是所謂的凸包。 計算凸包的一個著名演
最小凸包演算法(Convex Hull)(1)-Graham掃描法 -計算幾何-演算法導論
基本問題: 平面上有n個點p1,p2, ..., pn, 要求求出一個面積最小的凸多邊形,使得這個多邊形包含所有平面上的點。 根據演算法導論上提供的兩個方法做一些介紹: 演算法1: Graham掃描法 下面直接給出一段虛擬碼,方便描述: GRAHAM-SCAN(Q) {
計算幾何之凸包----Graham掃描法
計算幾何之凸包(convexHull)----Graham掃描法 關於凸包的嚴格定義,這裡不打算寫出來,大家可以自行Google或者百度,因為嚴格的數學定義反而不太好理解,用最通俗的話來解釋凸包:給定
凸包--Graham掃描法
一直聽大佬們說:凸包、凸包、凸包 一直不會。。。。。 然後。。。。 今天考試,考了一道計算幾何的簡單題。。。。 這,,,還是學一下吧。。 然後考試現場學習一下凸包演算法。 先理解一下凸包是啥東西。 看看這張圖 解釋一下凸包是什麼 如果你有一堆點(原諒我畫的很凌亂) 那麼,找到一個點集 依次連線這些點 使他們
凸包演算法詳解-Graham掃描法
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; struct nod
關於凸包——Graham掃描法
首先是凸包的第一種解法,graham掃描法。演算法的步驟如下: 1 首先我們要找到凸包的一個頂點,這個頂點的y座標要最小,相同的y的情況下,選擇更靠左的點 2 對給出的頂點集進行排序,按照極角遞增的順序進行排序?如何進行操作呢,我們可以用我們向量積的性質,如果向量積為正,b
凸包-Andrew演算法&&Graham掃描法
凸包簡介: 在二維平面上(二維凸包)給出若干個點,能夠包含這若干個點的面積最小的凸多邊形稱為凸包(可以想像有很多個釘子釘在牆上,然後用一個橡皮圈套在所有的釘子上,最後橡皮圈形成的就是一個凸包)。 Graham掃描法: Graham掃描法是一種基於極角排序的進行求解的
計算幾何 : 凸包學習筆記 --- Graham 掃描法
凸包 (只針對二維平面內的凸包) 一、定義 簡單的說,在一個二維平面內有n個點的集合S,現在要你選擇一個點集C,C中的點構成一個凸多邊形G,使得S集合的所有點要麼在G內,要麼在G上,並且保證這個凸多邊
凸包Graham掃描法->HDU3847
Graham掃描法求凸包 凸包定義: 點集Q的凸包(convex hull)是指一個最小凸多邊形,滿足Q中的點或者在多邊形邊上或者在其內。 凸包最常用的凸包演算法是Graham掃描法和Jarvis步進法。 Graham掃描法: 首先
二維求凸包 graham掃描法
graham掃描法求凸包的做法就是,選擇一個座標最靠近左下的點,然後作為原點,其他點按極座標排序,角度由小到大,角度想等r小的優先,然後將前兩個點放到棧中進行初始化,之後順序對每一個點進行判斷,只有該點向左發生了偏轉才將該點入棧,否則刪掉當前棧頂元素,再次判斷,直到發生了向
通過ArcEngine接口建立凸包(一)
geb ppt esp sqrt rect urn tar 次循環 arcengine 準備步驟: 1.先要能實現選擇點的功能,可以利用矩形選點要素的方法axMapControl1.TrackRectangle()。 2.要建立凸包,必須有存凸包(線要素)的文件,然後通過下
背包問題(貪心算法)
names 聯系 輸入 以及 多次 初始 單位 ace 而不是 註意:這是背包問題,而不是0-1背包問題,背包問題可以用貪心算法進行求解,但0-1無法用貪心算法求解,需要用動態規劃算法求解; 首先對貪心算法做一下總結,以及它與動態規劃算法的區別: 貪心算法兩個最重要的性
2018杭電多校第三場1007(凸包,極角排序)
棧模擬 include struct node 距離 然而 bit const 極角 #include<bits/stdc++.h>using namespace std;typedef const long long ll;struct node{ in