浙大ZOJ 1010 Area问题解决

来源:互联网 发布:python网页重定向 编辑:程序博客网 时间:2024/05/21 17:54

一、工程代码及算法设计注释

--------------------------------------------------area.h----------------------------------------------

#ifndef JLU_CCST_GNOME_TETRAVEX_H#define JLU_CCST_GNOME_TETRAVEX_H#include <vector>struct Point{double x,y;Point(double xx=0,double yy=0):x(xx),y(yy) {} ;};extern double caculatePolygonArea(std::vector<Point> polygon);extern void testCaculatePolygonArea();#endif//JLU_CCST_GNOME_TETRAVEX_H

--------------------------------------------------area.cpp----------------------------------------------

/**题目来源:浙大ACM在线测试——ZOJ,题目编号1010,题名"Area"URL:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1010Author:hellogdc<gdcjlu@163.com>Finish Time:2014.01.07*//**算法设计:一、总体算法设计:1. 判断给出的n多边形是否合法:检测任意两条非相邻线段是否有交点。2. 计算该多边形面积。二、如何判断线段是否相交线段A:(x1,y1),(x2,y2);线段B:(x3,y3),(x4,y4)。其中y1<y2,y3<y4.1. 先利用线段所在直线计算出直线交点直线用斜截式(y=kx+b)表示1.1 y=x*k1+b1,y=x*k2+b2:如k1=k2,则平行,肯定无交点;否则,计算出交点( (b2-b1)/(k1-k2),k1*(b2-b1)/(k1-k2)+b1 )1.2 y=x*k1+b1,x=b2:求出交点( b2,k1*b2+b1 )1.3 x=b1,y=x*k2+b2:求出交点( b1,k2*b1+b2 )1.4 x=b1,x=b2:如b1!=b2,则平行,肯定无交点;否则有无限多个交点,此时可利用( y1<=y3<=y2||y1<=y4<=y2 )这个逻辑式来判断是否相交。如该逻辑式为真,则2线段相交,否则,不相交。2. 判断交点是否同时在2条线段上执行到这里,则说明,2条线段所在执行肯定有交点了,设交点为(x,y)。利用( y1<=y<=y2&&y3<=y<=y4 )这个逻辑式进行判断。如为真,则说明2线段相交;否则,不相交。三、计算多边形面积关于多边形如何求面积方面的知识,有点忘了,到网上搜了一下,找到一个比较好的算法,该算法URL:http://blog.163.com/jasmine_han0324/blog/static/93264328200761925829514/.算法核心:对多边形A1A2A3、、、An(顺或逆时针都可以),设平面上有任意的一点P,则有:S(A1,A2,A3,、、、,An)= abs(S(P,A1,A2) + S(P,A2,A3)+、、、+S(P,An,A1))P是可以取任意的一点。当取P为(0,0)时就是下面的了:设点顺序 (x1 y1) (x2 y2)   ... (xn yn)则面积等于                    |x1  y1|    |x2  y2|             |xn  yn|         0.5 * abs( |      | +  |      | + ...... +  |      | )                    |x2  y2|    |x3  y3|             |x1  y1其中      |x1  y1|      |      |=x1*y2-y1*x2      |x2  y2|因此面积公式展开为:           |x1  y1|    |x2  y2|             |xn  yn|0.5 * abs( |      | +  |      | + ...... +  |      | )=0.5*abs(x1*y2-y1*x2+x2*y3-y2*x3+...+xn*y1-yn*x1)           |x2  y2|    |x3  y3|             |x1  y1|*/#include <iostream>#include <vector>#include "area.h"using namespace std;/**判断2条线段是否相交。如相交,则返回true;否则返回false。线段1:p1,p2.线段2:p3,p4.*/bool isTwoLineSegmentsIntersect(Point p1,Point p2,Point p3,Point p4){//确保p1.y<p2.y&&p3.y<p4.yPoint tmp;if(p1.y>p2.y){tmp=p1;p1=p2;p2=tmp;}if(p3.y>p4.y){tmp=p3;p3=p4;p4=tmp;}//1. 先利用线段所在直线计算出直线交点double y=0.0;//交点的y坐标//1.1 y=x*k1+b1,y=x*k2+b2:如k1=k2,则平行,肯定无交点;否则,计算出交点( (b2-b1)/(k1-k2),k1*(b2-b1)/(k1-k2)+b1 )if(p1.x!=p2.x&&p3.x!=p4.x){double k1=(p1.y-p2.y)/(p1.x-p2.x);double k2=(p3.y-p4.y)/(p3.x-p4.x);double b1=p1.y-k1*p1.x;double b2=p3.y-k2*p3.x;if(k1==k2)//平行,则肯定不相交return false;y=k1*(b2-b1)/(k1-k2)+b1;}//1.2 y=x*k1+b1,x=b2:求出交点( b2,k1*b2+b1 )else if(p1.x!=p2.x&&p3.x==p4.x){double k1=(p1.y-p2.y)/(p1.x-p2.x);double b1=p1.y-k1*p1.x;y=k1*(p3.x)+b1;}//1.3 x=b1,y=x*k2+b2:求出交点( b1,k2*b1+b2 )else if(p1.x==p2.x&&p3.x!=p4.x){double k2=(p3.y-p4.y)/(p3.x-p4.x);double b2=p3.y-k2*p3.x;y=k2*(p1.x)+b2;}//1.4 x=b1,x=b2:如b1!=b2,则平行,肯定无交点;否则有无限多个交点,此时可利用( y1<=y3<=y2||y1<=y4<=y2 )这个逻辑式//来判断是否相交。如该逻辑式为真,则2线段相交,否则,不相交。else{if(p1.x!=p3.x)//平行,则肯定不相交return false;if( (p1.y<=p3.y&&p3.y<=p2.y)||(p1.y<=p3.y&&p4.y<=p2.y))return true;return false;}//2. 判断交点是否同时在2条线段上//执行到这里,则说明,2条线段所在执行肯定有交点了,设交点为(x,y)。//利用( y1<=y<=y2&&y3<=y<=y4 )这个逻辑式进行判断。如为真,则说明2线段相交;否则,不相交。if( p1.y<=y&&y<=p2.y&&p3.y<=y&&y<=p4.y )return true;return false;}/**判断该点集构成的图形是否为多边形。如是,则返回true;否则,返回false。polygon:点集形成图形:相邻2点之间连线。*/bool isPolygonLegal(vector<Point> polygon){int nPoint=polygon.size();if(nPoint<=2)return false;//遍历n条线段for(int i=0;i<nPoint;i++){Point p1,p2;p1.x=polygon.at(i).x;p1.y=polygon.at(i).y;p2.x=polygon.at((i+1)%nPoint).x;p2.y=polygon.at((i+1)%nPoint).y;int nRest=nPoint-3;//与剩下的不相邻的n-3条线段进行相交性检测for(int j=0;j<nRest;j++){Point p3,p4;p3.x=polygon.at((i+j+2)%nPoint).x;p3.y=polygon.at((i+j+2)%nPoint).y;p4.x=polygon.at((i+j+3)%nPoint).x;p4.y=polygon.at((i+j+3)%nPoint).y;if( isTwoLineSegmentsIntersect(p1,p2,p3,p4) )return false;}}return true;}/**计算由点集polygon构成的多边形的面积,并将计算结果返回。前提:点集polygon能构成一个合法的多边形。面积公式:0.5*abs(x1*y2-y1*x2+x2*y3-y2*x3+...+xn*y1-yn*x1)*/double caculatePolygonArea(vector<Point> polygon){double sum=0.0;int nLoop=polygon.size()-1;for(int i=0;i<nLoop;i++){sum+=(polygon.at(i).x*polygon.at(i+1).y-polygon.at(i).y*polygon.at(i+1).x);}sum+=(polygon.at(nLoop).x*polygon.at(0).y-polygon.at(nLoop).y*polygon.at(0).x);return 0.5*fabs(sum);}///////////////////////////////////Test Cases///////////////////////////////////////void testIsTwoLineSegmentsIntersect(){Point p1,p2,p3,p4;bool flag=true;///////////////////////////////////////////////////////p1.x=4;p1.y=2;p2.x=4;p2.y=8;p3.x=2;p3.y=-3;p4.x=2;p4.y=45;flag=isTwoLineSegmentsIntersect(p1,p2,p3,p4);if(flag)cout<<"Intersects"<<endl;elsecout<<"Not intersects"<<endl;///////////////////////////////////////////////////////p1.x=0;p1.y=0;p2.x=1;p2.y=1;p3.x=0;p3.y=1;p4.x=1;p4.y=0;flag=isTwoLineSegmentsIntersect(p1,p2,p3,p4);if(flag)cout<<"Intersects"<<endl;elsecout<<"Not intersects"<<endl;///////////////////////////////////////////////////////p1.x=2;p1.y=2;p2.x=1;p2.y=1;p3.x=0;p3.y=1;p4.x=1;p4.y=0;flag=isTwoLineSegmentsIntersect(p1,p2,p3,p4);if(flag)cout<<"Intersects"<<endl;elsecout<<"Not intersects"<<endl;}void testIsPolygonLegal(){vector<Point> polygon;bool flag=true;///////////////////////////////////////////////////////polygon.clear();polygon.push_back(Point(0,0));polygon.push_back(Point(0,1));polygon.push_back(Point(0.5,0.5));polygon.push_back(Point(1,1));polygon.push_back(Point(1,0));flag=isPolygonLegal(polygon);if(flag)cout<<"This is Polygon"<<endl;elsecout<<"This is not Polygon"<<endl;///////////////////////////////////////////////////////polygon.clear();polygon.push_back(Point(0,0));polygon.push_back(Point(0,1));polygon.push_back(Point(1,0));polygon.push_back(Point(1,1));flag=isPolygonLegal(polygon);if(flag)cout<<"This is Polygon"<<endl;elsecout<<"This is not Polygon"<<endl;}void testCaculatePolygonArea(){vector<Point> polygon;bool flag=true;double area=0.0;///////////////////////////////////////////////////////polygon.clear();polygon.push_back(Point(0,0));polygon.push_back(Point(0,1));polygon.push_back(Point(0.5,0.5));polygon.push_back(Point(1,1));polygon.push_back(Point(1,0));flag=isPolygonLegal(polygon);if(flag){area=caculatePolygonArea(polygon);cout<<area<<endl;}elsecout<<"Impossible"<<endl;///////////////////////////////////////////////////////polygon.clear();polygon.push_back(Point(0,0));polygon.push_back(Point(0,1));polygon.push_back(Point(1,0));polygon.push_back(Point(1,1));flag=isPolygonLegal(polygon);if(flag){area=caculatePolygonArea(polygon);cout<<area<<endl;}elsecout<<"Impossible"<<endl;}

--------------------------------------------------main.cpp----------------------------------------------

#if 1#include "area.h"int main(){testCaculatePolygonArea();return 0;}#endif 

二、提交给ZOJ的代码——算法核心代码

注:提交后提示“Wrong Answer”,但是目前我还未找到错误的原因。

--------------------------------------------------submit_main.cpp----------------------------------------------

#include <iostream>#include <vector>#include <cmath>using namespace std;struct Point{double x,y;Point(double xx=0,double yy=0):x(xx),y(yy) {} ;};bool isTwoLinesIntersect(Point p1,Point p2,Point p3,Point p4){Point tmp;if(p1.y>p2.y){tmp=p1;p1=p2;p2=tmp;}if(p3.y>p4.y){tmp=p3;p3=p4;p4=tmp;}double y=0.0;if(p1.x!=p2.x&&p3.x!=p4.x){double k1=(p1.y-p2.y)/(p1.x-p2.x);double k2=(p3.y-p4.y)/(p3.x-p4.x);double b1=p1.y-k1*p1.x;double b2=p3.y-k2*p3.x;if(k1==k2)return false;y=k1*(b2-b1)/(k1-k2)+b1;}else if(p1.x!=p2.x&&p3.x==p4.x){double k1=(p1.y-p2.y)/(p1.x-p2.x);double b1=p1.y-k1*p1.x;y=k1*(p3.x)+b1;}else if(p1.x==p2.x&&p3.x!=p4.x){double k2=(p3.y-p4.y)/(p3.x-p4.x);double b2=p3.y-k2*p3.x;y=k2*(p1.x)+b2;}else{if(p1.x!=p3.x)return false;if( (p1.y<=p3.y&&p3.y<=p2.y)||(p1.y<=p3.y&&p4.y<=p2.y))return true;return false;}if( p1.y<=y&&y<=p2.y&&p3.y<=y&&y<=p4.y )return true;return false;}bool isPolygon(vector<Point> polygon){int nPoint=polygon.size();if(nPoint<=2)return false;for(int i=0;i<nPoint;i++){Point p1,p2;p1.x=polygon.at(i).x;p1.y=polygon.at(i).y;p2.x=polygon.at((i+1)%nPoint).x;p2.y=polygon.at((i+1)%nPoint).y;int nRest=nPoint-3;for(int j=0;j<nRest;j++){Point p3,p4;p3.x=polygon.at((i+j+2)%nPoint).x;p3.y=polygon.at((i+j+2)%nPoint).y;p4.x=polygon.at((i+j+3)%nPoint).x;p4.y=polygon.at((i+j+3)%nPoint).y;if( isTwoLinesIntersect(p1,p2,p3,p4) )return false;}}return true;}double polygonArea(vector<Point> polygon){double sum=0.0;int nLoop=polygon.size()-1;for(int i=0;i<nLoop;i++){sum+=(polygon.at(i).x*polygon.at(i+1).y-polygon.at(i).y*polygon.at(i+1).x);}sum+=(polygon.at(nLoop).x*polygon.at(0).y-polygon.at(nLoop).y*polygon.at(0).x);return 0.5*fabs(sum);}int main(){int nPoint;vector<vector<Point> > figures;while(cin>>nPoint){if(nPoint==0)break;vector<Point> points(nPoint);double x,y;for(int i=0;i<nPoint;i++){cin>>x>>y;points[i]=Point(x,y);}figures.push_back(points);}bool flag=false;for(int i=0;i<figures.size();i++){if(i!=0)cout<<endl;flag=isPolygon(figures.at(i));cout<<"Figure "<<(i+1)<<':';if(!flag){cout<<"Impossible"<<endl;continue;}double area=polygonArea(figures.at(i));cout<<area<<endl;}return 0;}


0 0
原创粉丝点击