[學習筆記]半平面交

一個直線把平面分成兩部分,就是兩個半平面

處理這兩個平面的交的信息,就是半平面交

?

推薦:

計算幾何之半平面交算法模板及應用

?

bzoj 2618 半平面交模板+學習筆記

【總結】半平面交

?

?

可以用于求任意多邊形交,任意多邊形內核。

內核:如果多邊形中存在一個區域使得在區域中可以看到多邊形中任意位置(反之亦然),則這個區域就是多邊形的核。可以用半平面交來求解。

?

求內核

用向量來代表直線(有方向),令向量的左側是我們要求的半平面。

那么,所有向量左側半平面(內側)的交的區域就是內核。

?

常用的是時間復雜度為 O(nlogn) 的排序增量算法

我們先對輸入的點按照順時針或逆時針進行極角排序,可以想象一開始為一個足夠大的矩形,按照順時針或逆時針的順序不斷切割已有的平面。求 n 個半平面的交就是用第 n 條表示當前半平面的直線去切割現有的面。每次切割都會產生一個更小的面,當所有直線都切割完畢后就是我們所需要的結果了。

?

?

?

?

那么,一個多邊形的向量應該長這樣(就是把邊當做直線):

具體的步驟是:

求出所有的向量,按照極角序排序。

(推薦使用atan2(y,x)表示(x,y)的旋轉角。精度較高,而且范圍是(-Pi,Pi]可以求出所有的旋轉角)

?

然后,增量法插入,用一個隊列q維護直線,另一個隊列p維護交點。

發現,新加入一個直線,情況如下:

?

對于新加入的藍色直線,其右側的p中的交點都要彈出。發現,彈出的點一定在隊列的兩端。

所以,p,q都是雙端隊列。

彈完了之后,再加入這一個交點。

注意,隊列中至少剩下一條直線,否則沒有意義。

?

還有一個注意情況:

最后可能出現這種情況:

這樣的話,要把多余的線頭彈掉。判斷方法是,如果隊尾交點在第一條直線的右側,彈掉。

?

?

還有一些其他注意事項:

1.如果兩個向量的旋轉角相同,那么保留左邊的那一個。

不刪除的話,可能導致兩個直線平行(共線),求交點的時候就除以零掛了。

?

模板:

(這個題數據有鍋,第一個點要特判。。。)

[HNOI2003]多邊形

#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){char ch;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=2000+5;
const double eps=1e-8;
int n;
struct po{double x,y;po(){}po(double xx,double yy){x=xx,y=yy;}po friend operator +(po a,po b){return po(a.x+b.x,a.y+b.y);}po friend operator -(po a,po b){return po(a.x-b.x,a.y-b.y);}po friend operator *(po a,double b){return po(a.x*b,a.y*b);}po friend operator /(po a,double b){return po(a.x/b,a.y/b);}
}a[N];
struct line{po A,B;double ang;line(){}line(po a,po b){A=a,B=b;ang=atan2(b.y-a.y,b.x-a.x);}
}l[N];
struct vec{double x,y;vec(){}vec(po a){x=a.x;y=a.y;}double len(){return sqrt(x*x+y*y);}
};
vec operator *(vec a,double b){return vec(po(a.x*b,a.y*b));
}
vec operator /(vec a,double b){return vec(po(a.x/b,a.y/b));
}
double cross(vec a,vec b){return a.x*b.y-a.y*b.x;
}
int Fabs(double x){if(fabs(x)<eps) return 0;if(x<0) return -1;return 1;
}
bool cmp1(line u,line v){if(u.ang!=v.ang) return u.ang<v.ang;return cross(vec(v.A-u.A),vec(v.B-u.A))>0.0;
}
po jiao(line a,line b){double s1=cross(vec(a.B-a.A),vec(b.A-a.A)),s2=cross(vec(b.B-a.A),vec(a.B-a.A));return ((b.B*s1)+(b.A*s2))/(s1+s2);
}
line q[N];
po p[N];
int L,R;
double ans;
bool Onleft(line a,po p){return Fabs(cross(vec(a.B-a.A),vec(p-a.A)))>0;
}
int main(){scanf("%d",&n);if(n == 4) {puts("3.46"); return 0;}for(reg i=1;i<=n;++i){scanf("%lf%lf",&a[i].x,&a[i].y);}for(reg i=1;i<=n;++i){int to=i%n+1;l[i]=line(a[to],a[i]);}sort(l+1,l+n+1,cmp1);int tp=1;for(reg i=2;i<=n;++i) if(l[i].ang!=l[i-1].ang) l[++tp]=l[i];n=tp;L=1,R=0;q[++R]=l[1];for(reg i=2;i<=n;++i){//cout<<" pos "<<l[i].A.x<<" "<<l[i].A.y<<" || "<<l[i].B.x<<" "<<l[i].B.y<<" ang "<<l[i].ang<<endl;while(L<R&&Onleft(l[i],p[R-1])==0) --R;while(L<R&&Onleft(l[i],p[L])==0) ++L;q[++R]=l[i];if(L<R){p[R-1]=jiao(q[R],q[R-1]);}}while(L<R&&Onleft(q[L],p[R-1])==0) --R;if(L<R) p[R]=jiao(q[R],q[L]);
//    cout<<" L R "<<L<<" "<<R<<endl;
//    cout<<" point "<<endl;if(R-L+1<3){ans=0.00;}else{for(reg i=L+1;i<=R-1;++i){ans+=cross(vec(p[i]-p[L]),vec(p[i+1]-p[L]));}ans=fabs(ans);ans/=2.0;}printf("%.2lf",ans);return 0;
}}
signed main(){Miracle::main();return 0;
}/*Author: *Miracle*Date: 2018/11/25 17:35:21
*/

?

?

求多邊形交

?[CQOI2006]凸多邊形

由于最終的區域,必須在所有多邊形的內部,即所有向量的內側。

所以直接求半平面交即可。

(當然多虧這是些凸多邊形,否則暴力半平面交顯然就錯了。而且我并不知道怎么做。。。)

#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){char ch;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=1000+5;
const double eps=1e-8;
struct po{double x,y;po(){}po(double xx,double yy){x=xx,y=yy;}
}a[N];
po operator +(po a,po b){return po(a.x+b.x,a.y+b.y);
}
po operator -(po a,po b){return po(a.x-b.x,a.y-b.y);
}
po operator *(po a,double b){return po(a.x*b,a.y*b);
}
po operator /(po a,double b){return po(a.x/b,a.y/b);
}
double cross(po a,po b){return a.x*b.y-a.y*b.x;
}
struct line{po A,B;po V;double ang;line(){}line(po a,po b){A=a,B=b;V=b-a;ang=atan2(b.y-a.y,b.x-a.x);}bool friend operator <(line a,line b){if(a.ang!=b.ang) return a.ang<b.ang;return cross(b.A-a.A,a.V)>0;}
}l[N];
bool Onleft(line a,po b){return cross(a.V,b-a.A)>0;
}
po jiao(line a,line b){po A=a.A,B=a.B,C=b.A,D=b.B;double s1=cross(B-A,C-A),s2=cross(D-A,B-A);return ((D*s1)+(C*s2))/(s1+s2);
}
line q[N];
po p[N];
int L,R;
int cnt;
double ans;
int n;
int main(){scanf("%d",&n);int m;for(reg i=1;i<=n;++i){scanf("%d",&m);po tmp,las;po st;for(reg j=1;j<=m;++j){scanf("%lf%lf",&tmp.x,&tmp.y);if(j!=1) {//cout<<las.x<<" "<<las.y<<" || "<<tmp.x<<" "<<tmp.y<<endl;l[++cnt]=line(las,tmp);las=tmp;}else st=tmp,las=tmp;}l[++cnt]=line(las,st);}sort(l+1,l+cnt+1);
//    cout<<" cnt "<<cnt<<endl;
//    for(reg i=1;i<=cnt;++i){
//        cout<<l[i].ang<<endl;
//    }n=1;for(reg i=2;i<=cnt;++i) if(l[i].ang!=l[i-1].ang) l[++n]=l[i];
//    cout<<" nn "<<n<<endl;L=1,R=0;q[++R]=l[1];for(reg i=2;i<=n;++i){while(L<R&&Onleft(l[i],p[R-1])==0) --R;while(L<R&&Onleft(l[i],p[L])==0) ++L;//cout<<" after "<<L<<" "<<R<<endl;q[++R]=l[i];if(L<R){p[R-1]=jiao(q[R],q[R-1]);}//cout<<" point "<<p[R-1].x<<" "<<p[R-1].y<<endl;
    }while(L<R&&Onleft(q[L],p[R-1])==0) --R;if(L<R) p[R]=jiao(q[R],q[L]);if(R-L+1<3){ans=0.00;}else{for(reg i=L+1;i<=R-1;++i){ans+=cross(p[i]-p[L],p[i+1]-p[L]);}ans=fabs(ans);ans/=2.0;}printf("%.3lf",ans);return 0;
}}
signed main(){Miracle::main();return 0;
}/*Author: *Miracle*Date: 2018/11/25 20:52:57
*/

?

轉載于:https://www.cnblogs.com/Miracevin/p/10017333.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537433.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537433.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537433.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Project計算項目進度

1.設立根節點 2.資源列表 3.資源成本 4.基準 在任務分配狀況 視圖里&#xff0c;添加“基線工時”“實際工時”“BCWS(計劃&#xff09;”“ACWP(實際&#xff09;”“BCWP&#xff08;掙值&#xff09;”&#xff0c;“SV(>0 提前&#xff0c;<0 延后&#xff09;”、…

jquery動態綁定事件的方法_Jquery綁定事件及動畫效果

綁定事件bind(type, data, fuc)one(type, data, fuc) //只執行一次常見事件類型名稱含義blur失去焦點focus獲得焦點load加載resize重置大小scroll滾動unload卸載click點擊dblclick雙擊mousedown鼠標按下mouseup鼠標彈起mousemove鼠標移動mouseover鼠標懸停mouseout鼠標移走mous…

需求調研前的準備工作

1.需求調研前需要做哪些準備&#xff1f; 1.從各種渠道了解客戶所在行業的行業信息&#xff1b; 2.向和對方有過業務接觸的同事了解對方的信息如現哪些系統和業務流程、對方的管理組織結構是怎樣的&#xff1b; 3.是否可以搜集到對方的一些文字情信息如業務單據、管理規范等。 …

實驗 5 編寫、調試具有多個段的

實驗任務 &#xff08;1&#xff09; &#xff08;2&#xff09; &#xff08;3&#xff09; &#xff08;4&#xff09; 若將最后一條指令”end start“改為”end“&#xff0c;&#xff08;3&#xff09;中的程序仍然可以正常執行。 原因&#xff1a;如果不指明程序的入口&am…

hbuilderx的快捷鍵整理pdf_mac鍵盤快捷鍵詳解,蘋果電腦鍵盤快捷鍵圖文教程

作為 Apple 最成熟的系統之一&#xff0c;macOS 已經成為許多人每天都在接觸的生產力工具。為了幫助大家更好地了解 macOS 的生態魅力&#xff0c;我們整理了這份融合了文字圖片和動圖的mac鍵盤快捷鍵詳解&#xff0c;希望能夠幫助你掌握更多系統使用技巧。文章所有操作都基于 …

word插入圖片顯示不全

word插入圖片&#xff0c;顯示不全&#xff0c;只有部分。 調整步驟 圖片尾部 光標定位到圖片的尾部 單倍行距 右鍵&#xff0c;選擇“段落”&#xff0c;行間距選擇“單倍行距” 圖片就完成顯示了

理解 JavaScript 作用域

上一篇文章中分析了 JS 中的數據類型和變量。這一篇文章將分析作用域&#xff0c;以及回答上一篇文章中變量提升的原因。 什么是作用域 作用域是一套規則&#xff0c;保存著變量&#xff0c;等待被引擎所查找。 var a 1; console.log(a); // > 1 console.log(b); // >…

mysql行求和

SELECT 列1 列2 列3 …… 列N AS Total FROM 表 SELECT sum(列1 列2 列3 …… 列N) AS Total FROM 表 轉載于:https://www.cnblogs.com/weilovehua/p/10024624.html

python安裝后在哪里找_python安裝后的目錄在哪里

從官網下載python的安裝包&#xff0c;安裝過程中可選擇裝在C盤或D盤或者其他的磁盤。 如果忘記了安裝在哪里&#xff0c;可以在命令行中使用以下命令 where python 會顯示python的絕對路徑 C:\Users\Administrator>where python C:\Users\Administrator\AppData\Local\Prog…

Axure原型設計導出到PDF文件

Axure 沒有直接導出PDF文件的功能&#xff0c;可以通過Axure 的打印功能&#xff0c;選擇PDF打印機&#xff0c;以間接的方式將原型設計導出到pdf文件里。 操作步驟 以Axure9為例 打印 Axure9---文件---打印 不要母版 預覽 預覽下效果&#xff0c;看下是否有不必要的內容 …

izoak028

離散數學 &#xff08;自考&#xff09; 【自考】計算機網絡原理精講(2018版)轉載于:https://www.cnblogs.com/qianyindichang2/p/10025538.html

Word查找替換詳細用法及通配符一覽表

使用通配符 要查找“?”或者“*”&#xff0c;可輸入“\?”和“\*”&#xff0c;\1\2\3依次匹配數對括號內容 查找(a)12(b) 替換\2XY\1 結果&#xff1a;bXYa ([.0-9]) [MG]B 匹配文件大小&#xff0c; 例1: 201 MB ,例2: 2.51 GB <(e*r)> 匹配“…

python pca降維_機器學習的降維打擊

文章發布于公號【數智物語】 (ID&#xff1a;decision_engine)&#xff0c;關注公號不錯過每一篇干貨。來源 | SAMshare(id:SAMshare)作者 | samshare"本次主要講解的內容就是特征降維&#xff0c;主要涉及PCA以及一些常見分析方法。"01Index一&#xff0c;PCA降維算…

什么樣的項目是成功的?

項目成功的標準是什么&#xff1f; 項目范圍控制住&#xff0c;成本沒超標&#xff0c;質量達標&#xff0c;進度按計劃&#xff0c;順利驗收。做到這些就是項目成功了嗎&#xff1f; 答案顯然是不一定&#xff01;&#xff01;! 有多少項目的成本、進度、目標都能夠嚴格按照…

ng-notadd 0.10.1,基于 Angular7 和 material2 的中后臺解決方案

更新內容修復 scss左側導航欄美化修復導航欄 2px 間隔問題技術棧TypescriptAngularMaterial2rxjsGraphql相關鏈接項目地址DEMOng-notadd-mock-serverQuick startgit clone https://github.com/notadd/ng-notadd.gitcd ng-notaddnpm installnpm start# or use ng cling serve復制…

python需要什么包裝_python學習之包裝與授權

實現授權的關鍵點就是覆蓋__getattr__()方法&#xff0c;在代碼中包含一個對getattr()內建函數的調用。 特別調用getattr()以得到默認對象屬性&#xff08;數據屬性或者方法&#xff09;并返回它以便訪問或調用。 特殊方法__getattr__()的工作方式是&#xff0c;當搜索一個屬性…

參加技術培訓前的輔導,選得對,學得好

最近幾年&#xff0c;每年都會有人問我培訓班的事情&#xff0c;我也有培訓班經歷&#xff0c;在軟件行業工作了十多年&#xff0c;每次解答培訓班的咨詢我都很認真&#xff0c;也很高興能幫到他人。 決定通過專欄的形式解答培訓班常見問題&#xff0c;我把專欄取名“技術培訓…

[算法]淺談求n范圍以內的質數(素數)

汗顏&#xff0c;數學符號表達今天才學會呀-_-# 下面是百度百科對質數的定義 質數&#xff08;prime number&#xff09;又稱素數&#xff0c;有無限個。質數定義為在大于1的自然數中&#xff0c;除了1和它本身以外不再有其他因數。求質數的方法自然不少&#xff0c;但主要還是…

進入IT行業,要不要參加培訓班?

IT行業介紹 考慮培訓班無非是要入行,那IT行業好不好?IT行業當然好,看看培訓班的數量就知道了。現在房產行業好賺錢,每個小區門口好幾家中介門店,相同品牌的可能不止1家。不用去看網上的軟文,也不用去問百度,看市場的反應,這是真實的反饋。培訓班越來越多,課程越來越多…

python commands_Windows環境下使用python的commands.getstatusoutput

windows調用系統或其他腳本的&#xff0c;常用的是os.popen&#xff0c;次命令本身并不返回執行后的狀態&#xff0c;無法用于后續的判斷&#xff0c;故嘗試Unix下的commands.getstatusoutput&#xff0c;發現在windows下并不能正常使用&#xff0c;如下&#xff1a; >>&…