首页 > 代码库 > 【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 是不一样的

141132351342That Nice Euler CircuitAcceptedC++0.0822014-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(几何+欧拉定理)