UVA 10652 凸包簡單問題

2021-08-01 09:04:49 字數 4595 閱讀 8790

題目鏈結

題意;見訓練指南272頁;

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define mm(a) memset(a,0,sizeof(a))

typedef long long ll;

typedef unsigned long long ull;

const double eps = 1e-14;

const int inf = 0x3f3f3f3f;

const double pi=acos(-1);

using namespace std;

struct point

point(double x, double y)

void read()

};bool cmp(point a,point b)

point point(double a)

};typedef point vector;

vector operator + (vector a, vector b)

vector operator - (vector a, vector b)

vector operator * (vector a, double p)

vector operator / (vector a, double p)

const double pi = acos(-1.0);

int dcmp(double x)

bool operator == (const point& a, const point& b)

bool operator < (const point& a, const point& b)

double torad(double ang)

double dot(vector a, vector b) //點積

double length(vector a) //向量的模

double angle(vector a, vector b) //向量夾角

double cross(vector a, vector b) //叉積

double area2(point a, point b, point c) //有向面積

double angle(vector v)

point getlineintersection(point p, vector v, point q, vector w)

vector rotate(vector a, double rad)

double distancetoline(point p, point a, point b)

vector anglebisector(point p, vector v1, vector v2)

//求線與x軸的真實角(0<=x<180)

double realanglewithx(vector a)

//求直線與圓的交點

int getlinecircleintersection(point p, vector v, circle c, vector&sol) else

}//兩圓相交

int getcirclecircleintersection(circle c1, circle c2, vector&sol)

if (dcmp(c1.r + c2.r - d) < 0) return 0;

if (dcmp(fabs(c1.r - c2.r) - d) > 0) return 0;

double a = angle(c2.c - c1.c);

double da = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));

point p1 = c1.point(a - da), p2 = c1.point(a + da);

sol.push_back(p1);

if(p1 == p2) return 1;

sol.push_back(p2);

return 2;

}//點到圓的切線

int gettangents(point p, circle c, vector *v) else

}//兩圓公切線

//a[i], b[i]分別是第i條切線在圓a和圓b上的切點

int getcircletangents(circle a, circle b, point *a, point *b)

//圓心距的平方

double d2 = (a.c.x - b.c.x) * (a.c.x - b.c.x) + (a.c.y - b.c.y) * (a.c.y - b.c.y);

double rdiff = a.r - b.r;

double rsum = a.r + b.r;

double base = angle(b.c - a.c);

//重合有無限多條

if (d2 == 0 && dcmp(a.r - b.r) == 0) return -1;

//內切

if (dcmp(d2 - rdiff * rdiff) == 0)

//有外公切線

double ang = acos((a.r - b.r) / sqrt(d2));

a[cnt] = a.point(base + ang); b[cnt] = b.point(base + ang); cnt++;

a[cnt] = a.point(base - ang); b[cnt] = b.point(base - ang); cnt++;

//一條內切線,兩條內切線

if (dcmp(d2 - rsum*rsum) == 0) else if (dcmp(d2 - rsum*rsum) > 0)

return cnt;

}//三角形外切圓

circle circumscribedcircle(point p1, point p2, point p3)

//三角形內切圓

circle inscribedcircle(point p1, point p2, point p3)

//求經過點p1,與直線(p2, w)相切,半徑為r的一組圓

int circlethroughapointandtangenttoalinewithradius(point p1, point p2, vector w, double r, vector&sol)

//給定兩個向量,求兩向量方向內夾著的圓的圓心。圓與兩線均相切,圓的半徑已給定

point centre_circletangenttwononparallellinewithradius(point p1, vector v1, point p2, vector v2, double r)

//求與兩條不平行的直線都相切的4個圓,圓的半徑已給定

int circlethroughapointandtangentalinewithradius(point p1, vector v1, point p2, vector v2, double r, point *sol)

//求與兩個相離的圓均外切的一組圓,三種情況

int circletangenttotwodisjointcircleswithradius(circle c1, circle c2, double r, point *sol)

double aa = length(c1.c - c2.c);

double bb = r + c1.r, cc = r + c2.r;

double rad = acos((aa * aa + bb * bb - cc * cc) / (2 * aa * bb));

vector w = rotate(u, rad);

point p0 = c1.c + w * t;

sol[0] = p0;

w = rotate(u, -rad);

p0 = c1.c + w * t;

sol[1] = p0;

return 2;

}//判斷點與圓的位置關係(自己寫的)

int pointincircle(point a,circle o)

int convexhull(point *p, int n, point* ch) //求凸包

int k = m;

for(int i = n-2; i >= 0; i--)

if(n > 1) m--;

return m;

}double polygonarea(point *p,int n)

{double area=0;

for(int i=1;i

需要注意的是rotate(double  rad)這個函式,向量的旋轉公式x'=xcosw+y+sinw這個w確實是角度,但是在程式中

比如90度,讀入的往往是90這個數字,所以需要提前轉化為弧度才能運用rotate這個函式(角度與弧度是等價的)

同時還有 %   採用  %%   這個格式輸出

凸包例題 UVa 10652

題意 有n塊矩形木板,你的任務是用乙個面積盡量小的凸多邊形把它們包起來,並計算出木板佔整個包裝面積的百分比。第一行輸入的是資料的組數,t 50 每組資料第一行為木板個數,n 600 以下n行每行五個實數,x,y,w,h,j。j是順時針旋轉的角度。sample input 4 7.5 6 3 0 8 ...

凸包 (簡單概念)

這裡先介紹點概念 一般是點集覆蓋問題 輸入各個點的座標 1.將各點排序 必須的 為保證形成圈,把 p0 在次放在點表的尾 部 2.準備堆疊 建立堆疊 s,棧指標設為t,將0 1 2 三個點壓入堆疊 s 3.對於下乙個點 i 只要 s t 1 s t i不做左轉 就反覆退棧 將 i壓入堆疊 s 4.堆...

凸包 (簡單概念)

這裡先介紹點概念 一般是點集覆蓋問題 輸入各個點的座標 1.將各點排序 必須的 為保證形成圈,把 p0 在次放在點表的尾 部 2.準備堆疊 建立堆疊 s,棧指標設為t,將0 1 2 三個點壓入堆疊 s 3.對於下乙個點 i 只要 s t 1 s t i不做左轉 就反覆退棧 將 i壓入堆疊 s 4.堆...