UVA 10652 Board Wrapping(計算幾何基礎,求凸包)
題目連結:傳送門
分析:
沒有什麼好說的就是求一個凸包就好了。可以當作模板、
程式碼如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-10;
//判斷符號,提高精度
int dcmp(double x){
if(fabs(x)<eps) return 0;
else return x < 0 ? -1 : 1;
}
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;
}
bool operator == (const Point B)const{
return dcmp(x-B.x)==0&&dcmp(y-B.y)==0;
}
};
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);
}
double Dot(Vector A, Vector B){//向量相乘
return A.x*B.x + A.y*B.y; //a*b*cos(a,b)
}
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;
}
/**
向量(x,y) 繞起點逆時針旋轉a度。
x' = x*cosa - y*sina
y' = x*sina + y*cosa
**/
Vector Rotate(Vector A,double a){
return Vector (A.x*cos(a)-A.y*sin(a),A.x*sin(a)+A.y*cos(a));
}
double trans(double ang){
return ang/180*acos(-1.0);
}
//叉積,可以用來判斷方向和求面積
double cross(Point a,Point b,Point c){
return (c.x-a.x)*(b.y-a.y) - (b.x-a.x)*(c.y-a.y);
}
//求多邊形的面積
double S(Point p[],int n)
{
double ans = 0;
p[n] = p[0];
for(int i=1; i<n; i++)
ans += cross(p[0],p[i],p[i+1]);
if(ans < 0) ans = -ans;
return ans / 2.0;
}
/**
求二維凸包Andrew演算法,將所有的點按x小到大(x相等,y小到大)排序
刪去重複的點,得到一個序列p1,p2...,然後把p1,p2放入凸包中,從p3
開始當新點再前進方向左邊時(可以用叉積判斷方向)繼續,否則,依次
刪除最近加入凸包的點,直到新點再左邊。
**/
int ConvexHull(Point *p,int n,Point *stack){
sort(p,p+n);
n=unique(p,p+n)-p;
int m=0;
for(int i=0; i<n; i++) {//如果不希望凸包的邊上有輸入的點則把兩個等號去掉
while(m>1&&cross(stack[m-2],p[i],stack[m-1])<=0) m--;
stack[m++]=p[i];
}
int k=m;
for(int i=n-2; i>=0; i--){
while(m>k&&cross(stack[m-2],p[i],stack[m-1])<=0)m--;
stack[m++]=p[i];
}
if(n>1) m--;
return m;
}
Vector p[2500];
Vector st[2500];
int main()
{
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
double x,y,w,h,a;
int num = 0;
double tot = 0;
for(int i=0; i<n; i++){
scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&a);
double ang = -trans(a);
Point o = Point(x,y);
p[num++] = o + Rotate(Point(-w/2,-h/2),ang);
p[num++] = o + Rotate(Point(w/2,-h/2),ang);
p[num++] = o + Rotate(Point(-w/2,h/2),ang);
p[num++] = o + Rotate(Point(w/2,h/2),ang);
tot+=w*h;
}
int m = ConvexHull(p,num,st);
double area = S(st,m);
printf("%.1lf %%\n",tot*100/area);
}
return 0;
}
/****
1
4
4 7.5 6 3 0
8 11.5 6 3 0
9.5 6 6 3 90
4.5 3 4.4721 2.2361 26.565
****/
相關文章
- 計算幾何(一):凸包問題(Convex Hull)
- 計算幾何 —— 二維幾何基礎 —— 距離度量方法
- 計算幾何
- 計算幾何:模板
- 計算幾何模板
- 【第一道計算幾何題】 UVA11178 Morley‘s Theorem (二維幾何,旋轉直線求求交點)REM
- Something about 計算幾何
- [筆記] 計算幾何筆記
- swust oj 249 求凸包面積板子
- SGU 124 Broken line(計算幾何)
- 計算幾何——平面最近點對
- POJ - 1556 【計算幾何 + 最短路】
- 【學習筆記】計算幾何筆記
- 邊緣計算、霧計算、雲端計算區別幾何?
- BNUOJ 12887 isumi(計算幾何+最大流)
- SGU 120 SGU 228 Archipelago(計算幾何)Go
- 計算機基礎計算機
- three.js基礎之幾何體Curve、GeometryJS
- 「管理數學基礎」3.1 凸分析:凸集與凸集分離定理、Farkas引理
- POJ 1113 Wall(思維 計算幾何 數學)
- 計算機基礎:位運算計算機
- 計算機基礎-網路基礎計算機
- 雲端計算基礎
- 計算機基礎-Socket計算機
- HNOI2016礦區(計算幾何+對偶圖)
- 計算機視覺—圖片幾何變換(2)計算機視覺
- [計算機網路] - 從英雄聯盟,看資料包何去何從?計算機網路
- CodeForces 887 E. Little Brother(計算幾何+二分)
- 【scipy 基礎】--空間計算
- 大學計算機基礎計算機
- TensorFlow 計算與智慧基礎
- 雲端計算基礎-0
- [計算幾何]圓與三角形是否相交
- Linux基礎命令---ipcalc計算iPLinuxPCA
- 百度造車,勝算幾何?
- [幾何]計算不規則多邊形的面積、中心、重心
- 計算機基礎知識複習計算機
- Scanner的進階使用——基礎計算
- 學計算機需要什麼基礎?計算機