【kuangbin专题】计算几何基础
1.poj2318 TOYS
传送:http://poj.org/problem?id=2318
题意:有m个点落在n+1个区域内。问落在每个区域的个数。
分析:二分查找落在哪个区域内。叉积判断点与线段的位置。
- #include<iostream>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int maxn=;
- struct point{
- int x,y;
- point(){ }
- point(int _x,int _y):x(_x),y(_y){}
- point operator +(const point &b) const{
- return point(x+b.x,y+b.y);
- }
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- int operator *(const point &b) const{
- return x*b.x,y*b.y;
- }
- int operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- };
- struct line{
- point s,e;
- line(){}
- line(point _s,point _e):s(_s),e(_e){}
- }box[maxn];
- int xmult(point p,point a,point b){
- return (b-a)^(p-a);
- }
- int ans[maxn];
- int main(){
- ios::sync_with_stdio(false);
- cin.tie();cout.tie();
- int n,m,x1,y1,x2,y2,ui,li,x,y;
- int _=;
- while (cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n){
- if (_!=) cout << endl;
- for (int i=;i<n;i++){
- cin >> ui >> li;
- box[i]=line(point(ui,y1),point(li,y2));
- }
- box[n]=line(point(x2,y1),point(x2,y2));
- memset(ans,,sizeof(ans));
- point p;
- for (int i=;i<m;i++){
- cin >> x >> y;
- p=point(x,y);
- int l=,r=n,mid,tmp;
- while (l<=r){
- mid=(l+r)>>;
- if (xmult(p,box[mid].s,box[mid].e)<){
- tmp=mid;
- r=mid-;
- }
- else l=mid+;
- }
- ans[tmp]++;
- }
- for (int i=;i<=n;i++) cout << i << ": " << ans[i] << endl;
- _++;
- }
- return ;
- }
poj2318
2.poj2398 Toy Storage
传送:http://poj.org/problem?id=2398
题意:与poj2318相同,输出要求输出有t(t>0)个玩具的格子数。
分析:同2318
- #include<iostream>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int maxn=;
- struct point{
- int x,y;
- point(){ }
- point(int _x,int _y):x(_x),y(_y){}
- point operator +(const point &b) const{
- return point(x+b.x,y+b.y);
- }
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- int operator *(const point &b) const{
- return x*b.x,y*b.y;
- }
- int operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- };
- struct line{
- point s,e;
- line(){}
- line(point _s,point _e):s(_s),e(_e){}
- //
- bool operator< (const line &b) const{
- return s.x<b.s.x;
- }
- }box[maxn];
- int cmp(line p,line q){
- return p.s.x<q.s.x;
- }
- int xmult(point p,point a,point b){
- return (a-p)^(b-p);
- }
- int ans[maxn],vis[maxn];
- int main(){
- ios::sync_with_stdio(false);
- cin.tie();cout.tie();
- int n,m,x1,y1,x2,y2,ui,li,x,y;
- while (cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n){
- for (int i=;i<n;i++){
- cin >> ui >> li;
- box[i]=line(point(ui,y1),point(li,y2));
- }
- box[n]=line(point(x2,y1),point(x2,y2));
- sort(box,box++n);
- memset(ans,,sizeof(ans));
- point p;
- for (int i=;i<m;i++){
- cin >> x >> y;
- p=point(x,y);
- int l=,r=n,mid,tmp;
- while (l<=r){
- mid=(l+r)>>;
- if (xmult(p,box[mid].s,box[mid].e)<){
- tmp=mid;
- r=mid-;
- }
- else l=mid+;
- }
- ans[tmp]++;
- }
- memset(vis,,sizeof(vis));
- for (int i=;i<=n;i++) if (ans[i]) vis[ans[i]]++;
- cout << "Box\n";
- for (int i=;i<=n;i++){
- if (!vis[i]) continue;
- cout << i << ": " << vis[i] << endl;
- }
- }
- return ;
- }
poj2398
3.poj3304 Segments
传送:http://poj.org/problem?id=3304
题意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。
分析:如果有存在这样的直线,过投影相交区域作直线的垂线,该垂线必定与每条线段相交,问题转化为问是否存在一条线和所有线段相交。
直线肯定经过两个端点。两两枚举端点(包括同一条线段),判断直线和线段是否相交。
- #include<iostream>
- #include<cstring>
- #include<cmath>
- #include<algorithm>
- using namespace std;
- const double eps=1e-;
- const int maxn=;
- struct point{
- double x,y;
- point(){}
- point(double _x,double _y):x(_x),y(_y){}
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- double operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- double operator *(const point &b) const{
- return x*b.x+y*b.y;
- }
- };
- struct line{
- point s,t;
- line(){}
- line(point _s,point _t):s(_s),t(_t){}
- }a[maxn];
- int sgn(double x){
- if (fabs(x)<eps) return ;
- if (x<) return -;
- return ;
- }
- double xmult(point p,point a,point b){ // PA X PB
- return (a-p)^(b-p);
- }
- int seg_inter_line(line l1,line l2){
- return sgn(xmult(l2.s,l1.s,l1.t))*sgn(xmult(l2.t,l1.s,l1.t))<=;
- }
- double dist(point a,point b){
- return sqrt((b-a)*(b-a));
- }
- int check(line l1,int n){
- if (sgn(dist(l1.s,l1.t))==) return ;
- for (int i=;i<n;i++)
- if (seg_inter_line(l1,a[i])==) return ;
- return ;
- }
- int main(){
- int t,n; cin >> t;
- double x1,x2,y1,y2;
- while (t--){
- cin >> n;
- for (int i=;i<n;i++){
- cin >> x1 >> y1 >> x2 >> y2;
- a[i]=line(point(x1,y1),point(x2,y2));
- }
- int f=;
- for (int i=;i<n;i++){
- for (int j=;j<n;j++){
- if (check(line(a[i].s,a[j].s),n) || check(line(a[i].s,a[j].t),n)
- || check(line(a[i].t,a[j].s),n) || check(line(a[i].t,a[j].t),n)){
- f=; break;
- }
- }
- }
- if (f) cout << "Yes!\n";
- else cout << "No!\n";
- }
- }
poj3304
4.poj1269 Intersecting Lines
传送:http://poj.org/problem?id=1269
题意:给出两条直线,问两条直线的位置关系(平行,重合,相交)。相交的话输出交点。
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<cmath>
- #include<cstring>
- using namespace std;
- const double eps=1e-;
- int sgn(double x){
- if (fabs(x)<eps) return ;
- if (x<) return -;
- return ;
- }
- struct point{
- double x,y;
- point(){}
- point(double _x,double _y):x(_x),y(_y){}
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- double operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- double operator *(const point &b) const{
- return x*b.x+y*b.y;
- }
- };
- struct line{
- point s,t;
- line(){}
- line(point _s,point _t):s(_s),t(_t){}
- pair<point,int> operator &(const line &b) const{
- point res=s;
- if (sgn((s-t)^(b.s-b.t))==){
- if (sgn((b.s-s)^(b.t-s))==) return make_pair(res,); //两直线重合
- else return make_pair(res,); //两直线平行
- }
- double k=((s-b.s)^(b.s-b.t))/((s-t)^(b.s-b.t));
- res.x+=(t.x-s.x)*k;
- res.y+=(t.y-s.y)*k;
- return make_pair(res,); //两直线相交
- }
- };
- int main(){
- int n; cin >> n;
- double x1,x2,y1,y2;
- line l1,l2;
- cout << "INTERSECTING LINES OUTPUT\n";
- for (int i=;i<n;i++){
- cin >> x1 >> y1 >> x2 >> y2;
- l1=line(point(x1,y1),point(x2,y2));
- cin >> x1 >> y1 >> x2 >> y2;
- l2=line(point(x1,y1),point(x2,y2));
- pair<point,int> ans=l1&l2;
- if (ans.second==) printf("POINT %.2f %.2f\n",ans.first.x,ans.first.y);
- else if (ans.second==) printf("NONE\n");
- else printf("LINE\n");
- }
- cout << "END OF OUTPUT\n";
- return ;
- }
poj1269
5.poj1556 The Doors
传送:http://poj.org/problem?id=1556
题意:10×10的方阵内有若干个墙壁,墙壁之间有空隙(可通过),问从(0,5)到(10,5)的最短路。
分析:建图,线段两两判断是否相交,不相交就建边。然后跑最短路。(数据较小,随便最短路算法。
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const double eps=1e-;
- const double inf=1e20;
- const int maxn=;
- double mp[maxn][maxn];
- int sgn(double x){
- if (fabs(x)<eps) return ;
- if (x<) return -;
- return ;
- }
- struct point{
- double x,y;
- point(){}
- point(double _x,double _y):x(_x),y(_y){}
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- double operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- double operator *(const point &b) const{
- return x*b.x+y*b.y;
- }
- };
- struct line{
- point s,e;
- line(){}
- line(point _s,point _e):s(_s),e(_e){}
- }a[maxn];
- double dist(point a,point b){
- return sqrt((b-a)*(b-a));
- }
- int inter(line l1,line l2){
- return
- max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
- && max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
- && max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
- && max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
- && sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
- && sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
- }
- double floyd(int n){
- for (int i=;i<=n;i++)
- for (int j=;j<=n;j++)
- for (int k=;k<=n;k++)
- if (mp[i][k]+mp[k][j]<mp[i][j]) mp[i][j]=mp[i][k]+mp[k][j];
- return mp[][n];
- }
- int main(){
- int n; double x,y1,y2,y3,y4;
- while (cin >> n && n!=-){
- for (int i=;i<=n;i++){
- cin >> x >> y1 >> y2 >> y3 >> y4;
- a[*i-]=line(point(x,y1),point(x,y2));
- a[*i]=line(point(x,y3),point(x,y4));
- }
- for (int i=;i<=*n+;i++)
- for (int j=;j<=*n+;j++)
- if (i==j) mp[i][j]=;else mp[i][j]=inf;
- for (int i=;i<=*n;i++){
- int l=(i+)/;
- int f=;
- point tmp;
- if (i&) tmp=a[(i+)/].s; else tmp=a[(i+)/].e;
- for (int j=;j<l;j++)
- if (inter(a[*j-],line(point(,),tmp))==
- && inter(a[*j],line(point(,),tmp))==) f=;
- if (f) mp[][i]=mp[i][]=dist(point(,),tmp);
- f=;
- for (int j=l+;j<=n;j++)
- if (inter(a[*j-],line(point(,),tmp))==
- && inter(a[*j],line(point(,),tmp))==) f=;
- if (f) mp[i][*n+]=mp[*n+][i]=dist(point(,),tmp);
- }
- for (int i=;i<=*n;i++){
- for (int j=i+;j<=*n;j++){
- int l1=(i+)/,l2=(j+)/;
- int f=;
- point p1,p2;
- if (i&) p1=a[(i+)/].s; else p1=a[(i+)/].e;
- if (j&) p2=a[(j+)/].s; else p2=a[(j+)/].e;
- for (int k=l1+;k<l2;k++)
- if (inter(a[*k-],line(p1,p2))==
- && inter(a[*k],line(p1,p2))==) f=;
- if (f) mp[i][j]=mp[j][i]=dist(p1,p2);
- }
- }
- int f=;
- for (int i=;i<=n;i++)
- if (inter(a[*i-],line(point(,),point(,)))==
- && inter(a[*i],line(point(,),point(,)))==) f=;
- if (f) mp[][*n+]=mp[*n+][]=;
- double ans=floyd(*n+);
- printf("%.2f\n",ans);
- }
- return ;
- }
poj1556
6.poj2653 Pick-up sticks
传送:http://poj.org/problem?id=2653
题意:问有多少线段不与比它编号大的相交。
分析:线段交直接暴力判断。
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- using namespace std;
- const double eps=1e-;
- const int maxn=;
- int sgn(double x){
- if (fabs(x)<eps) return ;
- if (x<) return -;
- return ;
- }
- struct point{
- double x,y;
- point(){}
- point(double _x,double _y):x(_x),y(_y){}
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- double operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- double operator *(const point &b) const{
- return x*b.x+y*b.y;
- }
- };
- struct line{
- point s,e;
- line(){}
- line(point _s,point _e):s(_s),e(_e){}
- }a[maxn];
- double dist(point a,point b){
- return sqrt((b-a)*(b-a));
- }
- int inter(line l1,line l2){
- return
- max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
- && max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
- && max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
- && max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
- && sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
- && sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
- }
- bool vis[maxn];
- int main(){
- ios::sync_with_stdio(false);
- cin.tie();cout.tie();
- int n; double x1,x2,y1,y2;
- while (cin >> n && n){
- for (int i=;i<n;i++){
- cin >> x1 >> y1 >> x2 >> y2;
- a[i]=line(point(x1,y1),point(x2,y2));
- vis[i]=;
- }
- for (int i=;i<n;i++){
- for (int j=i+;j<n;j++){
- if (inter(a[i],a[j])){vis[i]=;break;}
- }
- }
- cout << "Top sticks: ";
- int f=;
- for (int i=;i<n;i++){
- if (!vis[i]) continue;
- if (f){cout << i+;f=;}
- else cout << ", " << i+;
- }
- cout << ".\n";
- }
- }
poj2653
7.poj1066 Treasure Hunt
传送:http://poj.org/problem?id=1066
题意:在金字塔内有一个宝藏p(x,y);现在要取出这个宝藏在金字塔内有许多墙为了进入宝藏所在的房间必须把墙炸开但是炸墙只能炸每个房间墙的中点求将宝藏运出城堡所需要的最小炸墙数。
- #include<iostream>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- #include<cstring>
- using namespace std;
- const double dx[]={,,,},dy[]={,,,};
- const double eps=1e-;
- const int maxn=;
- int sgn(double x){
- if (fabs(x)<eps) return ;
- if (x<) return -;
- return ;
- }
- struct point{
- double x,y;
- point(){}
- point(double _x,double _y):x(_x),y(_y){}
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- double operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- double operator *(const point &b) const{
- return x*b.x+y*b.y;
- }
- }p[*maxn];
- struct line{
- point s,e;
- line(){}
- line(point _s,point _e):s(_s),e(_e){}
- }a[maxn];
- int inter(line l1,line l2){
- return
- max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
- && max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
- && max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
- && max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
- && sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
- && sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
- }
- int main(){
- int n; double x1,y1,x2,y2;
- while (cin >> n){
- for (int i=;i<=n;i++){
- cin >> x1 >> y1 >> x2 >> y2;
- a[i]=line(point(x1,y1),point(x2,y2));
- p[*i-]=point(x1,y1); p[*i]=point(x2,y2);
- }
- point s;
- cin >> x1 >> y1;
- s=point(x1,y1);
- int ans=;
- for (int i=;i<=*n;i++){
- line l1=line(s,p[i]);
- int res=;
- for (int j=;j<=n;j++)
- if (inter(l1,a[j])) res++;
- ans=min(res,ans);
- }
- for (int i=;i<;i++){
- line l1=line(s,point(dx[i],dy[i]));
- int res=;
- for (int j=;j<=n;j++)
- if (inter(l1,a[j])) res++;
- ans=min(ans,res+);
- }
- cout << "Number of doors = " << ans << endl;
- }
- return ;
- }
poj1066
8.poj1410 Intersection
传送:http://poj.org/problem?id=1410
题意:给定一个矩阵和线段,若线段在矩阵内或与矩阵某条边相交,输出T,否则输出F。
分析:判断线段与四条边线段交。再判断是否在矩阵内。
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- using namespace std;
- const double eps=1e-;
- const int maxn=;
- int sgn(double x){
- if (fabs(x)<eps) return ;
- if (x<) return -;
- return ;
- }
- struct point{
- double x,y;
- point(){}
- point(double _x,double _y):x(_x),y(_y){}
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- double operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- double operator *(const point &b) const{
- return x*b.x+y*b.y;
- }
- }p[maxn];
- struct line{
- point s,e;
- line(){}
- line(point _s,point _e):s(_s),e(_e){}
- };
- int inter(line l1,line l2){
- return
- max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
- && max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
- && max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
- && max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
- && sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
- && sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
- }
- int onseg(point p,line l){
- return
- sgn((l.s-p)^(l.e-p))== &&
- sgn((p.x-l.s.x)*(p.x-l.e.x))<= &&
- sgn((p.y-l.s.y)*(p.y-l.e.y))<=;
- }
- //判断点在凸多边形内
- //点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
- //点的编号:0~n-1
- //返回值:
- //-1:点在凸多边形外
- //0:点在凸多边形边界上
- //1:点在凸多边形内
- int inConvexPoly(point a,point p[],int n){
- for (int i=;i<n;i++){
- if (sgn((p[i]-a)^(p[(i+)%n]-a))<) return -;
- else if (onseg(a,line(p[i],p[(i+)%n]))) return ;
- }
- return ;
- }
- int main(){
- int t; cin >> t;
- double x1,y1,x2,y2;
- while (t--){
- cin >> x1 >> y1 >> x2 >> y2;
- line l=line(point (x1,y1),point(x2,y2));
- cin >> x1 >> y1 >> x2 >> y2;
- if (x1>x2) swap(x1,x2); if (y1>y2) swap(y1,y2);
- p[]=point(x1,y1);p[]=point(x2,y1);p[]=point(x2,y2);p[]=point(x1,y2);
- if (inter(l,line(p[],p[])) || inter(l,line(p[],p[]))
- || inter(l,line(p[],p[])) || inter(l,line(p[],p[]))){
- cout << "T\n";continue;
- }
- if (inConvexPoly(l.s,p,)>= || inConvexPoly(l.e,p,)>=){
- cout << "T\n"; continue;
- }
- cout << "F\n";
- }
- return ;
- }
poj1410
9.poj1696 Space Ant
传送:http://poj.org/problem?id=1696
题意:一只蚂蚁只会向左转,现在给出平面上很多个点,求解一种走法能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉。
分析:对于题目所输入的点,先找出最左下方的顶点(即纵坐标最小的顶点),然后对剩下的顶点按照对与左下点的极角排序,然后反复找最左下的点,反复进行极角排序,同时记录排序后左下的顶点。
极角排序方法:利用叉积,看向量p1和p2的叉积是否小于零,是则说明p1在p2逆时针方向,即p1的极角比p2的大,极角相同则按离p0距离降序排序。
- #include<iostream>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- const double eps=1e-;
- const int maxn=;
- int sgn(double x){
- if (fabs(x)<eps) return ;
- if (x<) return -;
- return ;
- }
- struct point{
- double x,y;
- int id;
- point(){}
- point(double _x,double _y):x(_x),y(_y){}
- point operator -(const point &b) const{
- return point(x-b.x,y-b.y);
- }
- double operator ^(const point &b) const{
- return x*b.y-y*b.x;
- }
- double operator *(const point &b) const{
- return x*b.x+y*b.y;
- }
- }p[maxn];
- double dist(point a,point b){
- return sqrt((a-b)*(a-b));
- }
- int pos;
- int cmp(point a,point b){
- double tmp=(a-p[pos])^(b-p[pos]);
- if (sgn(tmp)==) return dist(a,p[pos])<dist(b,p[pos]);
- else if (sgn(tmp)<) return false;
- else return true;
- }
- int main(){
- int t,n; cin >> t;
- double x,y;
- while (t--){
- cin >> n;
- for (int i=;i<n;i++){
- cin >> p[i].id >> p[i].x >> p[i].y;
- if (p[i].y<p[].y || p[i].y==p[].y && p[i].x<p[].x) swap(p[i],p[]);
- }
- pos=;
- for (int i=;i<n;i++){
- sort(p+i,p+n,cmp);
- pos++;
- }
- cout << n;
- for (int i=;i<n;i++) cout << " " << p[i].id;
- cout << endl;
- }
- }
poj1696
10.poj3347 Kadj Squares
传送:http://poj.org/problem?id=3347
题意:给出n个边长的正方形,要求尽可能贴着放。问最后从上往下看能看到哪几个正方形。
分析:每新增一个正方形,就让他与左侧的每一个正方形贴紧,求的其左端坐标,最终结果一定是最大的那个。然后求的相应的最右端坐标。这样就转化为了线段,最后用朴素的n2算法求出每条线段没有被覆盖的长度,如果长度大于0,即可输出。
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- const int maxn=;
- struct node{
- int len,l,r;
- }a[maxn];
- int main(){
- int n;
- while (cin >> n && n){
- for (int i=;i<n;i++){
- cin >> a[i].len; //将图形扩大根2倍,len为对角线长度的一半
- a[i].l=;
- for (int j=;j<i;j++){
- a[i].l=max(a[i].l,a[j].r-abs(a[i].len-a[j].len));
- }
- a[i].r=a[i].l+*a[i].len;
- }
- for (int i=;i<n;i++){
- for (int j=;j<i;j++){
- if (a[i].l<a[i].r){
- if (a[i].len<a[j].len && a[i].l<a[j].r) a[i].l=a[j].r;
- else if (a[i].len>a[j].len && a[i].l<a[j].r) a[j].r=a[i].l;
- }
- }
- }
- for (int i=;i<n;i++){
- if (a[i].l<a[i].r) cout << i+ << " ";
- }
- cout << endl;
- }
- return ;
- }
poj3347
11.poj1654 Area
传送:http://poj.org/problem?id=1654
题意:从原点开始,超八个方向走。问最后形成的多边形面积。
分析:rt。直接求多边形面积。
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- using namespace std;
- const int dx[]={,-,,,-,,,-,,},dy[]={,-,-,-,,,,,,};
- const int maxn=;
- typedef long long ll;
- struct point{
- int x,y;
- point(){}
- point(int _x,int _y):x(_x),y(_y){}
- ll operator ^(const point &b)const{
- return x*b.y-y*b.x;
- }
- };
- struct polygon{
- int n;
- point p[maxn];
- void add(point q){p[n++]=q;}
- ll getarea(){
- ll sum=;
- for (int i=;i<n;i++) sum+=(p[i]^(p[(i+)%n]));
- return sum<?-sum:sum;
- }
- };
- polygon C;
- int main(){
- char ch;
- int t,k; cin >> t;
- while (t--){
- C.n=;
- ll x=,y=;
- while (cin >> ch && ch!=''){
- k=ch-'';
- x+=dx[k]; y+=dy[k];
- C.add(point(x,y));
- }
- ll ans=C.getarea();
- if (ans&) cout << ans/ << ".5\n";
- else cout << ans/ << endl;
- }
- return ;
- }
poj1654
12.poj2954 Triangle
传送:http://poj.org/problem?id=2954
题意:求三角形内部有多少格点。
分析:pick定理。S=a+b/2-1。a代表多边形内部的格点,b代表多边形边上的格点。S代表多边形面积。
- #include<iostream>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- typedef long long ll;
- const int maxn=;
- struct point{
- int x,y;
- point(){}
- point(int _x,int _y):x(_x),y(_y){}
- ll operator ^(const point &b)const{
- return x*b.y-y*b.x;
- }
- };
- struct polygon{
- int n;
- point p[maxn];
- void add(point q){p[n++]=q;}
- ll getarea(){
- ll sum=;
- for (int i=;i<n;i++) sum+=(p[i]^p[(i+)%n]);
- return sum<?-sum:sum;
- }
- };
- polygon C;
- ll gcd(ll a,ll b){
- if (b==) return a;
- else return gcd(b,a%b);
- }
- int main(){
- int x1,x2,x3,y1,y2,y3;
- while (cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3){
- if (!x1 && !x2 && !x3 && !y1 && !y2 && !y3) break;
- C.n=;
- C.add(point(x1,y1));C.add(point(x2,y2));C.add(point(x3,y3));
- ll area=C.getarea();
- int b=;
- for (int i=;i<C.n;i++){
- b+=gcd(abs(C.p[i].x-C.p[(i+)%C.n].x),abs(C.p[i].y-C.p[(i+)%C.n].y));
- }
- cout << (area+-b)/ << endl; //S=a+b/2-1
- }
- return ;
- }
poj2954
【kuangbin专题】计算几何基础的更多相关文章
- [kuangbin]专题六 最小生成树 题解+总结
kuangbin专题链接:https://vjudge.net/article/752 kuangbin专题十二 基础DP1 题解+总结:https://www.cnblogs.com/RioTian ...
- nyis oj 68 三点顺序 (计算几何基础)
三点顺序 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 如今给你不共线的三个点A,B,C的坐标,它们一定能组成一个三角形,如今让你推断A,B,C是顺时针给出的还是逆 ...
- kuangbin专题 数论基础 part1?
线段树专题太难了,那我来做数学吧! 但数学太难了,我......(扯 这两天想了做了查了整理了几道数学. 除了一些进阶的知识,像莫比乌斯反演,杜教筛,min25学不会我跳了,一些基础的思维还是可以记录 ...
- 【BZOJ】1043: [HAOI2008]下落的圆盘(计算几何基础+贪心)
http://www.lydsy.com/JudgeOnline/problem.php?id=1043 唯一让我不会的就是怎么求圆的周长并QAAQ... 然后发现好神!我们可以将圆弧变成$[0, 2 ...
- 计算几何基础——矢量和叉积 && 叉积、线段相交判断、凸包(转载)
转载自 http://blog.csdn.net/william001zs/article/details/6213485 矢量 如果一条线段的端点是有次序之分的话,那么这种线段就称为 有向线段,如果 ...
- BZOJ_1610_[Usaco2008_Feb]_Line连线游戏_(计算几何基础+暴力)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1610 给出n个点,问两两确定的直线中,斜率不同的共有多少条. 分析 暴力枚举直线,算出来斜率放 ...
- 二维计算几何基础题目泛做(SYX第一轮)
题目1: POJ 2318 TOYS 题目大意: 给一个有n个挡板的盒子,从左到右空格编号为0...n.有好多玩具,问每个玩具在哪个空格里面. 算法讨论: 直接叉积判断就可以.注意在盒子的边界上面也算 ...
- 最小生成树 kuangbin专题最后一个题
题目链接:https://cn.vjudge.net/contest/66965#problem/N 注释:这道题需要用krustra,用prim的话可能会超时.并且在计算距离的时候要尽量减少步骤,具 ...
- kuangbin专题十六 KMP&&扩展KMP HDU2087 剪花布条
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? Input输入中含有一些数据,分别是成对出现的花布条和小 ...
随机推荐
- 如何安全管理windows系统日志,windows系统日志的报表和告警
如何安全管理windows系统日志,windows系统日志的报表和告警 无论大小,每个拥有IT基础设施的组织都容易发生内部安全攻击.您的损失等同于黑客的收益:访问机密数据.滥用检索到的信息.系统崩溃, ...
- vue2.0 移动端,下拉刷新,上拉加载更多插件 转:
转自:http://www.cnblogs.com/gmajip/p/7204072.html <template lang="html"> <div class ...
- Python sys.argv[] 的用法
sys.argv变量是一个list, 执行 python abc.py a b c 时, sys.argv[0]为 abc.py sys.argv[1]为 a sys.argv[2]为 b sys.a ...
- set集合的排序
在hibernate的OneToMany的实体关联的时候,one端的set是无序的,可是需要按照顺序来搞的话就比较麻烦了. 下面给出一个例子. Set<DiaryPicture> diar ...
- tomcat7 安装 windows 服务
tomcat 可以安装成windows 服务,这样 每次启动就不需要启动tomcat了. 具体配置: 1.修改 service.bat 在行首添加 set "JAVA_HOME=E:\jdk ...
- java常用设计模式八:代理模式
一.概述 代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象. 其特征是代理类与委托类有同样的接口,真正的核心业务逻辑还是在实际对象里面. 二.为什么要使用代理模式 当 ...
- openstack之镜像管理
概览 [root@cc07 fast-pulsar]# glance help | grep image [--os-image-url OS_IMAGE_URL] [--os-image-api-v ...
- XML xmlns
xmlns xml namespaces 参考 http://www.w3school.com.cn/tags/tag_prop_xmlns.asp http://www.w3school.com.c ...
- 用Html创建简历
用最基本的html实现简历的创建 代码 <!doctype html> <html> <head><meta charset="utf-8" ...
- HDU 3078 LCA转RMQ
题意: n个点 m个询问 下面n个数字表示点权值 n-1行给定一棵树 m个询问 k u v k为0时把u点权值改为v 或者问 u-v的路径上 第k大的数 思路: LCA转RMQ求出 LCA(u,v) ...