UVA LA3218 找边界,PSLG
来源:互联网 发布:天庭淘宝店 宁小北txt 编辑:程序博客网 时间:2024/06/10 20:23
分析:
本题是求PSLG得外轮廓,需要借助与前面所说的“类似卷包裹”的算法。具体来说,首先找到x坐标最小的点(如果有多个,找y坐标最小的点),然后开始“卷包裹”。
首先找到初始边。
然后每次都执行如下操作。
首先看看当前线段是否和其他线段相交(根据题意,一定是规范相交),如果不想交,说明可以直接走到当前线段的终点,否则走到最近的交点就得停下来,接下来转弯
并继续前进。转弯时如果有多条路可以走,选择那条右转的最厉害的线段。转回原点以后,整个过程结束。
这题代码比较繁琐,不容易懂,看了大牛的代码看了好久也没完全理解,
lower_bound()函数讲解:
函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置
举例如下:
一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标
则
pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。
pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。
pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。
所以,要记住:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!~
返回查找元素的第一个可安插位置,也就是“元素值>=查找值”的第一个元素的位置
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<cctype>#include<string>#include<set>#include<map>#include<queue>#include<stack>#include<vector>using namespace std;const double eps=1e-6;int dcmp(double x){ if(fabs(x)<eps) return 0; return x>0?1:-1; //return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);}struct point{ double x; double y; point(){} point(double x,double y):x(x),y(y){} void in() { cin>>x>>y; } void out() { cout<<x<<' '<<y<<endl; } point operator + (const point &t) const { return point(x+t.x,y+t.y); } point operator - (const point &t) const { return point(x-t.x,y-t.y); } point operator * (const double &t) const { return point(x*t,y*t); } point operator / (const double &t) const { return point(x/t,y/t); } bool operator < (const point &t) const { return (dcmp(x-t.x)<0||(dcmp(x-t.x)==0&&dcmp(y-t.y)<0)); } bool operator == (const point &t) const { return dcmp(x-t.x) ==0 &&dcmp(y-t.y)==0; }};double cross(point a,point b){ return a.x*b.y-a.y*b.x;}double dot(point a,point b){ return a.x*b.x+a.y*b.y;}double length(point a){ return sqrt(dot(a,a));}point nomal(point t){ double l=length(t); return point(-t.y/l,t.x/l);}struct line{ point p; point v; double ang; line() {} line(point p,point v):p(p),v(v){ ang=atan2(v.y,v.x); } bool operator < (const line &l) const { return ang<l.ang; }};bool onleft(line l,point p){ return cross(l.v,p-l.p)>0;}point getintersection(line a,line b){ point u=a.p-b.p; double t=cross(b.v,u)/cross(a.v,b.v); return a.p+a.v*t;}bool sgementproperintersection(point a1,point a2,point b1,point b2){ double c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1), c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1); return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;}bool onsegment(point p,point a1,point a2){ return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<0;}typedef vector<point> Polygon;double PolygonArea(Polygon poly){ double area=0; int n=poly.size(); for(int i=1;i<n-1;i++) { area+=cross(poly[i]-poly[0],poly[(i+1)%n]-poly[0]); } return area/2;}struct Edge{ int from; int to; double ang;};const int maxn=10000+10;struct PSLG{ int n,m,face_cnt; double x[maxn],y[maxn]; vector<Edge> edges; vector<int> G[maxn]; int vis[maxn*2]; int left[maxn*2]; int prev[maxn*2]; vector<Polygon> faces; double area[maxn]; void init(int n) { this->n=n; for(int i=0;i<n;i++) { G[i].clear(); } edges.clear(); faces.clear(); } double getAngle(int from,int to) { return atan2(y[to]-y[from],x[to]-x[from]); } void AddEdge(int from,int to) { edges.push_back((Edge) {from,to,getAngle(from,to)}); edges.push_back((Edge) {to,from,getAngle(to,from)}); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } void Build() { for(int u=0;u<n;u++) { int d=G[u].size(); for(int i=0;i<d;i++) for(int j=i+1;j<d;j++) { if(edges[G[u][i]].ang>edges[G[u][j]].ang) swap(G[u][i],G[u][j]); } for(int i=0;i<d;i++) { prev[G[u][(i+1)%d]]=G[u][i]; } } memset(vis,0,sizeof(vis)); face_cnt=0; for(int u=0;u<n;u++) { for(int i=0;i<G[u].size();i++) { int e=G[u][i]; if(!vis[e]) { face_cnt++; Polygon poly; for(;;) { vis[e]=1; left[e]=face_cnt; int from=edges[e].from; point P(x[from],y[from]); poly.push_back(P); e=prev[e^1]; if(e==G[u][i]) break; } faces.push_back(poly); } } } for(int i=0;i<face_cnt;i++) { area[i]=PolygonArea(faces[i]); } }};PSLG g;const int maxp=100+5;point P[maxp];point V[maxp*(maxp-1)/2+maxp];int n,c;int ID(point p){ return lower_bound(V,V+c,p)-V;}Polygon simplify(const Polygon &poly) //去共线{ Polygon ans; int n=poly.size(); for(int i=0;i<n;i++) { point a=poly[i]; point b=poly[(i+1)%n]; point c=poly[(i+2)%n]; if(dcmp(cross(b-a,c-b))!=0) { ans.push_back(b); } } return ans;}void build_graph(){ for(int i=0;i<n;i++) { V[i]=P[i]; } vector<double> dist[maxp]; c=n; for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { if(sgementproperintersection(P[i],P[(i+1)%n],P[j],P[(j+1)%n])) { point ip=getintersection(line(P[i],P[(i+1)%n]-P[i]),line(P[j],P[(j+1)%n]-P[j])); V[c++]=ip; dist[i].push_back(length(ip-P[i])); dist[j].push_back(length(ip-P[j])); } } sort(V,V+c); c=unique(V,V+c)-V; g.init(c); for(int i=0;i<c;i++) { g.x[i]=V[i].x; g.y[i]=V[i].y; } for(int i=0;i<n;i++) //按在那条边上来统计 { point v=P[(i+1)%n]-P[i]; double len=length(v); v=v/len; dist[i].push_back(0); dist[i].push_back(len); sort(dist[i].begin(),dist[i].end()); int sz=dist[i].size(); for(int j=1;j<sz;j++) { point a=P[i]+v*dist[i][j-1]; point b=P[i]+v*dist[i][j]; if(a==b) continue; g.AddEdge(ID(a),ID(b)); } } g.Build();}int main(){ while(cin>>n&&n) { for(int i=0;i<n;i++) cin>>P[i].x>>P[i].y; build_graph(); Polygon poly; for(int i=0;i<g.faces.size();i++) { if(g.area[i]<0) { poly=g.faces[i]; reverse(poly.begin(),poly.end()); poly=simplify(poly); break; } } int start=0; int m=poly.size(); cout<<m<<endl; for(int i=0;i<m;i++) { if(poly[i]<poly[start]) { start=i; } } for(int i=start;i<m;i++) { printf("%.4f %.4f\n",poly[i].x,poly[i].y); } for(int i=0;i<start;i++) { printf("%.4f %.4f\n",poly[i].x,poly[i].y); } } return 0;}
就暂时抄写了一遍,留着慢慢理解吧。
- UVA LA3218 找边界,PSLG
- UVA LA 2797 PSLG 线段闭合圈 神奇的精度问题
- uva--10714+找规律
- UVA 1620(找规律)
- UVa 11300 找金币
- uva-1347经典dp,边界设置很重要
- uva 10479(找规律+递归)
- UVA 11853(找连通块)
- 边界
- 平面直线图(PSLG)模板
- uva 579 ClockHands(找规律)
- Decode the tape - UVa 10878 找规律
- uva 846 Steps(找规律)
- UVA 264 Count on Canton 找规律
- uva 11853 Paintball dfs找连通块
- UVA Searching for Nessy(找规律)
- uva 11636 Hello World!(找规律)
- uva 10706 Number Sequence(找规律)
- CSS3属性笔记(七)
- git从创建到使用的一些简单命令
- linux下rm命令改造成将文件移动至回车站
- WebService(5)——一个webService请求的流程
- adb install命令没反应 只有光标显示
- UVA LA3218 找边界,PSLG
- 数据结构之双循环链表
- 每周积累
- apache 下载和设置
- 反射机制和内省机制的区别
- Eclipse: Problem: NoGoalSpecifiedException
- Pixel perfect 2d in 4.3?
- 欢迎使用CSDN-markdown编辑器
- wordlist1-page1