首页 > 代码库 > 【UVA】1342 - That Nice Euler Circuit(几何+欧拉定理)
【UVA】1342 - That Nice Euler Circuit(几何+欧拉定理)
E 为边数 ,V 为点数,F为面数
那么 F = E + 2 - V(其中包括了一个无限大的面)
这道题被自己的习惯坑了一下#define MAXD 300 + 10 和#define MAXD 310 是不一样的
14113235 | 1342 | That Nice Euler Circuit | Accepted | C++ | 0.082 | 2014-08-29 15:12:20 |
自己的代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define INF 1 << 30 #define eps 1e-10 #define Vector Point #define MAXD 310 /*=============================================*/ int dcmp(double x){ if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } struct Point{ double x; double y; Point(double a = 0,double b = 0): x(a),y(b) {}; friend bool operator < (Point p,Point q){ if(p.x == q.x) return p.y < q.y; else return p.x < q.x; } friend Vector operator + (Point p,Point q){ return Vector(p.x + q.x , p.y + q.y); } friend Vector operator - (Point p,Point q){ return Vector(p.x - q.x , p.y - q.y); } friend Vector operator * (Point p,double t){ return Vector(p.x * t , p.y * t); } friend Vector operator / (Point p,double t){ return Vector(p.x / t , p.y / t); } friend bool operator == (Point p,Point q){ return dcmp(p.x - q.x) == 0 && dcmp(p.y - q.y) == 0; } }; double Dot(Vector p, Vector q){ //向量点积 return p.x * q.x + p.y * q.y; } double Length(Vector p){ //向量长度 return sqrt(p.x * p.x + p.y * p.y); } double Angle(Vector p ,Vector q){ return acos( Dot(p, q) /( Length(p) * Length(q) ) ); } double Cross(Vector p,Vector q){ return p.x * q.y - p.y * q.x; } double Area2(Point a,Point b,Point c){ return Cross(a - b , c - b); } Vector Rotate(Vector p,double angle){ return Vector(p.x * cos(angle) - p.y * sin(angle), p.x * sin(angle) + p.y * cos(angle)); } Vector Normal(Vector p){ //求法向量 double L = Length(p); return Vector( - p.y / L , p.x / L); } Point GetLineCross(Point p,Vector v,Point q,Vector w){ //交点 Vector u = p - q; double t = Cross(w,u) / Cross(v,w); return p + v * t; } double Distance(Point p,Point a,Point b){ //点到射线的距离 Vector v1 = b - a; Vector v2 = p - a; return fabs(Cross(v1,v2)) / Length(v1); } double Distance2(Point p,Point a,Point b){ if(a == b) return Length(p - a); Vector v1 = b - a , v2 = p - a, v3 = p - b; if(dcmp(Dot(v1,v2)) < 0) return Length(v2); else if(dcmp(Dot(v1,v3)) > 0) return Length(v3); else return fabs(Cross(v1,v2))/ Length(v1); } Point GetLinePoint(Point p,Point a,Point b){ //点在线上的投影 Vector v = b - a; return a + v * (Dot(v, p -a ) / Dot(v,v)); } bool If_Cross(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 If_InLine(Point p,Point a1,Point a2){ return dcmp(Cross(a1 - p , a2 - p)) == 0 && dcmp(Dot(a1 - p , a2 - p)) < 0; } Point point[MAXD],V[MAXD * MAXD]; int main(){ int n,Case = 1; while(scanf("%d",&n) && n){ for(int i = 0 ; i < n ; i++){ scanf("%lf%lf",&point[i].x,&point[i].y); V[i] = point[i]; } n--; int c = n ,e = n ;//分别为点数和线段书 for(int i = 0 ; i < n ; i++){ for(int j = i + 1 ; j < n ; j++){ if(If_Cross(point[i],point[i + 1],point[j],point[j + 1])){ V[c++] = GetLineCross(point[i],point[i + 1] - point[i],point[j],point[j + 1] - point[j]); } } } sort(V,V + c); c = unique(V,V + c) - V;//去除重复元素,返回首地址 for(int i = 0 ; i < c ; i++){ for(int j = 0 ; j < n ; j++){ if(If_InLine(V[i],point[j],point[j + 1])) e++; } } printf("Case %d: There are %d pieces.\n",Case ++ , e + 2 - c); } return 0; }
网上有的代码更清晰,模板也更好,copy一下:
#include <iostream> #include <cstdlib> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <stack> #include <algorithm> using namespace std; const double eps = 1e-10; struct Point { double x, y; Point(double x = 0, double y = 0) : x(x), y(y) { } bool operator < (const Point& a) const { if(a.x != x) return x < a.x; return y < a.y; } }; typedef Point Vector; Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } bool operator == (const Point& a, const Point &b) { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; } double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } double Length(Vector A) { return sqrt(Dot(A, A)); } double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); } double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } double Area2(Point A, Point B, Point C) { return Cross(B-A, C-A); } Vector Rotate(Vector A, double rad) { return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad)); } Point GetIntersection(Point P, Vector v, Point Q, Vector w) { Vector u = P-Q; double t = Cross(w, u) / Cross(v, w); return P+v*t; } bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) { double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1); double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1); return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0; } double PolygonArea(Point* p, int n) { double area = 0; for(int i = 1; i < n-1; i++) area += Cross(p[i]-p[0], p[i+1]-p[0]); return area; } bool OnSegment(Point p, Point a1, Point a2) { return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0; } Point read_point() { Point A; scanf("%lf%lf", &A.x, &A.y); return A; } int n; const int maxn = 310; Point P[maxn], V[maxn*maxn]; int read_case() { scanf("%d", &n); if(!n) return 0; for(int i = 0; i < n; i++) P[i] = read_point(), V[i] = P[i]; n--; return 1; } void solve() { int v = n, e = n; for(int i = 0; i < n; i++) { for(int j = i+1; j < n; j++) { if(SegmentProperIntersection(P[i], P[i+1], P[j], P[j+1])) { V[v++] = GetIntersection(P[i], P[i+1]-P[i], P[j], P[j+1]-P[j]); //新增加的点数 } } } sort(V, V+v); //排序 v = unique(V, V+v) - V; //去重 for(int i = 0; i < v; i++) { for(int j = 0; j < n; j++) //判断新增加的边数 { if(OnSegment(V[i], P[j], P[j+1])) e++; } } int ans = e+2-v; printf("There are %d pieces.\n", ans); } int main() { int times = 0; while(read_case()) { printf("Case %d: ", ++times); solve(); } return 0; }
【UVA】1342 - That Nice Euler Circuit(几何+欧拉定理)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。