浙大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
- 浙大ZOJ 1010 Area问题解决
- 浙大ZOJ 1005 Jugs问题解决
- 浙大ZOJ 1011 NTA问题解决
- 浙大ZOJ 1012 Mainframe问题解决
- 浙大ZOJ 1004 Anagrams by Stack问题解决
- 浙大ZOJ 1008 Gnome Tetravex问题解决
- zoj-1010-Area
- zoj 1010 Area
- ZOJ 1010 Area
- ZOJ 1010 Area
- 浙大ZOJ 1003 Crashing Ballon问题解决及其他人的做法
- 浙大ZOJ 1009 Enigma问题解决及别人的解决方案
- zoj 1010 Area (求面积 叉积)
- zoj 1010 Area【线段相交问题】
- zoj-1010 Area 多边形判别与面积
- ZOJ--1010:Area(线段判交问题)
- zoj 浙大ACM1005
- 浙大ACM-ZOJ 1049
- Linux平台总线驱动设备模型
- Python中list、tuple、dict区别
- XMPP高级编程---使用Jquery和Javascript学习笔记二
- Windows Phone零距离开发(Composite Thread组合线程)
- 堆排序时间复杂度理解
- 浙大ZOJ 1010 Area问题解决
- init方法代码进行了整理(自备)
- MTK Android Driver :camera
- Http Error-Code List
- java内部类的总结!
- C#异步
- 一位射频技术支持工程师的工作感悟
- CentOS GraphicsMagick安装
- java 获取当前应用程序和系统的属性特征,比如路径、用户名..