3____计算几何
3.1____叉积判断点线关系
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,x1,x2,y1,y2;
/// n为分区数,m为玩具数,左上坐标,右下坐标
struct Point
{
int x,y;
};
//typedef Point Vector;
//Vector oprator + ( Vector A,Vector B ) { return Vector ( A.x + B.x , A.y + B.y ); }
//Vector oprator - ( Vector A,Vector B ) { return Vector ( )}
struct Line
{
Point a,b;
}line[5001];
int cnt[5001];
inline int Cross(Point p1,Point p2) ///求叉积
{
return p1.x * p2.y - p1.y * p2.x;
}
inline bool dir(int k ,Point p)
{
Point a,b;
a.x = line[k].a.x - p.x;
a.y = line[k].a.y - p.y;
b.x = line[k].b.x - p.x;
b.y = line[k].b.y - p.y;
return Cross( a,b ) > 0;
}
inline int Find(Point p)
{
int l = 1, r = n ;
while( l <= r )
{
int mid = ( l + r) >> 1;
if( dir(mid,p) ) l = mid + 1;
else r = mid - 1;
}
return r;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while( cin >> n )
{
if( n == 0) break;
memset(cnt,0,sizeof cnt);
cin >> m >> x1 >> y1 >> x2 >> y2;
for(int i = 1; i <= n ; i++)
{
line[i].a.y = y1;
line[i].b.y = y2;
cin >> line[i].a.x >> line[i].b.x;
}
///对应区间
for(int i = 1; i <= m ; i++)
{
Point p;
cin >> p.x >> p.y;
++cnt[ Find(p) ];
}
///打印
for(int i = 0 ; i <= n ;i ++) cout << i <<": " << cnt[i] <<endl;
cout<< endl;
}
return 0;
}
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
const int N = 105;
const double eps = 1e-8;
int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
///square of a double
inline double sqr(double x) { return x * x; }
struct Point
{
double x,y;
Point(){} ///no arguments constructor
Point(double _x,double _y) {
x = _x , y = _y; ///arguments constructor
}
bool operator == (Point b) const{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (Point b) const{
return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
}
double operator ^ (const Point &b) const{
return x * b.y - y * b.x;
}
Point operator - (const Point &b) const{
return Point(x - b.x , y - b.y);
}
Point operator + (const Point &b) const{
return Point(x + b.x , y + b.y);
}
}s[N*2];
struct Line
{
Point s,e;
Line(){}
Line( Point _s, Point _e ){ s =_s ; e=_e; }
///直线与线段相交判断
///-*this line -v seg
///2规范相交,1非规范相交,0不相交
bool linecrossseg(Line v){
return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
}
}line[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--)
{
int n,x1,x2,y1,y2;
cin >> n;
for(int i = 1 ; i <= n ; i++)
{
cin >> line[i].s.x >> line[i].s.y;
cin >> line[i].e.x >> line[i].e.y;
s[i*2 -1] = line[i].s , s[i*2] = line[i].e;
}
bool flag = 0;
///对每个点进行枚举
for(int i = 1; i <= 2 * n ; i++)
{
if(flag) break;
for(int j = i + 1 ; j <= 2 * n ; j++)
{
//cout << s[i].x << ' ' << s[i].y << " | " <<s[j].x << ' '<< s[j].y <<endl;
Line te(s[i],s[j]);
if( s[i].x == s[j].x && s[i].y == s[j].y ) continue;
///验证这个枚举的线是不是与每个线段都相交
int k;
for(k = 1;k <= n; k++)
//cout << te.linecrossseg( line[k] ) << endl;
if( !te.linecrossseg( line[k] ) ) break;
if(k == n +1) flag = 1;
//cout << k << endl;
}
}
if(flag) cout << "Yes!" <<endl;
else cout << "No!" << endl;
// cout<< endl;
}
return 0;
}
3.2____多边形重心
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double pi = acos( -1.0);
///Compares a double to zero
int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
///square of a double
inline double sqr(double x) { return x * x; }
/////////////////////////////////////////////////
struct Point
{
double x,y;
Point(){} ///no arguments constructor
Point(double _x,double _y) {
x = _x , y = _y; ///arguments constructor
}
bool operator == (Point b) const{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (Point b) const{
return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
}
///数量积
Point operator - (const Point &b) const{
return Point(x - b.x , y - b.y);
}
Point operator + (const Point &b) const{
return Point(x + b.x , y + b.y);
}
Point operator * (const double &k) const{
return Point(x * k , y * k );
}
Point operator / (const double &k) const{
return Point(x / k , y / k);
}
///叉积
double operator ^ (const Point &b) const{
return x * b.y - y * b.x;
}
///点积
double operator * (const Point &b) const{
return x * b.x + y * b.y;
}
///线段的长度
double len(){
return hypot(x,y); ///<cmath>
}
///长度的平方
double len2(){
return x * x + y * y;
}
///返回两点的距离
double distance(Point p){
return hypot( x - p.x , y - p.y );
}
};
const int maxp = 10000010;
struct polygon
{
int n;
Point p[maxp];
//Line l[maxp];
double getarea()
{
double sum = 0;
for(int i = 0; i<n ; i++){
sum += p[i].distance(p[(i+1)%n]);
}
return sum;
}
Point getbarycentre()
{
Point ret(0,0);
double area = 0;
for(int i = 1; i < n - 1; i++){
double tmp = (p[i] - p[0] )^ ( p[i +1] -p[0] );
// printf("%.2f
",tmp);
if(sgn(tmp) == 0)continue;
area += tmp;
ret.x += ( p[0].x + p[i].x + p[i +1].x )/ 3 * tmp;
ret.y += ( p[0].y + p[i].y + p[i+1].y ) /3 * tmp;
}
if( sgn(area) ) ret = ret /area;
return ret;
}
}pol;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
pol.n = n ;
//scanf("%d%d",&pol.p[0].x,&pol.p[0].y);
for(int i = 0; i < n ; i++)
{
scanf("%lf %lf",&pol.p[i].x,&pol.p[i].y);
// pol.l[i-1].s.x = pol.p[i-1].x;
// pol.l[i-1].s.y = pol.p[i-1].y;
// pol.l[i-1].e.x = pol.p[i].x;
// pol.l[i-1].e.y = pol.p[i].y;
}
Point ans = pol.getbarycentre();
if( ans.x > -0.001 && ans.x < 0.0 ) ans.x = 0;
if( ans.y > -0.001 && ans.y < 0.0 ) ans.y = 0;
printf("%.2f %.2f
",ans.x ,ans.y);
}
return 0;
}
3.3____极角排序
思路
:事先将两个点连成线,然后用叉积来判断第三个点在这个线的左边还是右边,
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <math.h>
using namespace std;
const double eps = 1e-8;
const double pi = acos( -1.0);
///Compares a double to zero
int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
///square of a double
inline double sqr(double x) { return x * x; }
struct Point
{
double x,y;
int num;
Point(){} ///no arguments constructor
Point(double _x,double _y) {
x = _x , y = _y; ///arguments constructor
}
bool operator == (Point b) const{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (Point b) const{
return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
}
///数量积
Point operator - (const Point &b) const{
return Point(x - b.x , y - b.y);
}
Point operator + (const Point &b) const{
return Point(x + b.x , y + b.y);
}
Point operator * (const double &k) const{
return Point(x * k , y * k );
}
Point operator / (const double &k) const{
return Point(x / k , y / k);
}
///叉积
double operator ^ (const Point &b) const{
return x * b.y - y * b.x;
}
///点积
double operator * (const Point &b) const{
return x * b.x + y * b.y;
}
///返回两点的距离
double distance(Point p){
return sqrt( sqr( x- p.x ) + sqr(y - p.y) );
}
}P[510];
Point ans[510];
Point init;
bool cmp(Point a,Point b)
{
if( fabs( (a - init)^( b - init ) ) < eps ) /// 如果极角相同,比较距离
{
return init.distance(a) < init.distance(b);
}
else return ( (a - init) ^ (b - init) )> 0;
}
int main()
{
ios::sync_with_stdio( false);
cin.tie(0);
int n,t;
cin >> t;
while(t--)
{
cin >> n;
int miny = 100000000;
for(int i = 1 ; i <= n ; i++){
cin >> P[i].num >> P[i].x >> P[i].y;
if( P[i].y < miny ) miny = P[i].y;
}
init.x = 0,init.y = miny;
for(int i = 1 ; i <= n ; i++)
{
sort(P+i,P+1+n,cmp);
ans[i] = P[i];
init = P[i];
}
cout << n << ' ';
for(int i = 1; i <= n ; i++ )
cout << ans[i].num << ' ';
cout <<endl;
}
return 0;
}
3.4____计算几何,思维题
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const double eps = 1e-8;
const double pi = acos( -1.0);
///Compares a double to zero
int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
///square of a double
inline double sqr(double x) { return x * x; }
/////////////////////////////////////////////////
struct Point
{
double x,y;
Point(){} ///no arguments constructor
Point(double _x,double _y) {
x = _x , y = _y; ///arguments constructor
}
bool operator == (Point b) const{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (Point b) const{
return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
}
///数量积
Point operator - (const Point &b) const{
return Point(x - b.x , y - b.y);
}
Point operator + (const Point &b) const{
return Point(x + b.x , y + b.y);
}
Point operator * (const double &k) const{
return Point(x * k , y * k );
}
Point operator / (const double &k) const{
return Point(x / k , y / k);
}
///叉积
double operator ^ (const Point &b) const{
return x * b.y - y * b.x;
}
///点积
double operator * (const Point &b) const{
return x * b.x + y * b.y;
}
///线段的长度
double len(){
return hypot(x,y); ///<cmath>
}
///长度的平方
double len2(){
return x * x + y * y;
}
///返回两点的距离
double distance(Point p){
return hypot( x - p.x , y - p.y );
}
};
struct Line
{
vector<char> croset;
char name;
Point s,e;
Line(){}
Line( Point _s, Point _e ){ s =_s ; e=_e; }
void input(Point _p1,Point _p2)
{
s = _p1,e = _p2;
}
///直线与线段相交判断
///-*this line -v seg
///2规范相交,1非规范相交,0不相交
bool linecrossseg(Line v){
return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
}
///点与直线关系
///1在左侧
///2在右侧
///3在直线
int relation(Point p){
int c = sgn( (p-s) ^ (e -s) );
if(c < 0) return 1;
else if(c > 0) return 2;
else return 3;
}
///点在线段上的判断
bool point_on_seg(Point p){
return sgn((p-s)^(e-s) ) == 0 && sgn( (p-s)*(p-e) ) <= 0 ;
}
///两向量平行(对应直线平行或重合)
bool parallel(Line v){
return sgn( (e-s)^( v.e - v.s ) ) == 0;
}
///两直线关系 0-平行,1-重合,2-相交
int linecrossline(Line v){
if( (*this).parallel(v) )
return v.relation(s) == 3;
return 2;
}
///得到交点,需先判断直线是否相交
Point crosspoint(Line v){
double a1 = ( v.e - v.s ) ^ ( s - v.s );
double a2 = ( v.e - v.s ) ^ ( e - v.s );
return Point( (s.x * a2 - e.x * a1)/(a2 - a1) , (s.y *a2 - e.y *a1)/(a2 - a1));
}
///两线段相交判断
///2 规范相交
///1 非规范相交
///0 不想交
int segcrossseg(Line v) {
int d1 = sgn((e - s) ^ (v.s - s));
int d2 = sgn((e - s) ^ (v.e - s));
int d3 = sgn((v.e - v.s) ^ (s - v.s));
int d4 = sgn((v.e - v.s) ^ (e - v.s));
if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2)return 2;
return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) ||
(d2 == 0 && sgn((v.e - s) * (v.e - e)) <= 0) ||
(d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) ||
(d4 == 0 && sgn((e - v.s) * (e - v.e)) <= 0);
}
};
struct polygon
{
int num; ///点的数量
Point p[4];
Line l[4];
struct cmp{
Point p;
cmp(const Point &p0){ p = p0;}
bool operator()( const Point &aa ,const Point &bb){
Point a = aa,b = bb;
int d = sgn( (a-p)^(b-p) );
if(d == 0) return sgn( a.distance(p) - b.distance(p)) < 0;
return d > 0;
}
};
/// 3在顶点上
/// 2在边上
/// 1在内部
/// 0在外面
int Point_in_polygon(Point tep)
{
for(int i = 0 ; i < num ; i++){
if( p[i] == tep ) return 3;
}
for(int i = 0 ; i < num ; i++){
if( l[i].point_on_seg(tep) ) return 2;
}
int tecnt = 0;
for(int i = 0 ; i < num ; i++)
{
int j = (i + 1) % num;
int c = sgn( (tep - p[j]) ^ (p[i] - p[j]) );
int u = sgn( p[i].y - tep.y );
int v = sgn( p[j].y - tep.y );
if( c > 0 && u < 0 && v >=0 ) tecnt ++;
if( c < 0 && u >= 0 && v < 0 ) tecnt --;
}
return tecnt != 0;
}
}pol;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t,n;
cin >> t;
while(t--)
{
Point p1,p2,j1,j3;
cin >> p1.x >> p1.y >> p2.x >> p2.y >> j1.x >> j1.y >> j3.x >> j3.y;
if( j1.x > j3.x ) swap(j1,j3);
Line lp(p1,p2);
Point j2,j4;
j2.x = j3.x,j2.y = j1.y,j4.x = j1.x ,j4.y = j3.y;
polygon pol;
pol.p[0] = j1;
pol.p[1] = j2;
pol.p[2] = j3;
pol.p[3] = j4;
pol.l[0].input(j1,j2);pol.l[1].input(j2,j3),pol.l[2].input(j3,j4),pol.l[3].input(j4,j1);
pol.num = 4;
bool flag = 0;
for(int i = 0; i < 4 ; i++)
if( lp.segcrossseg(pol.l[i]) > 0 ){
flag = 1;
break;
}
if( flag ) cout <<'T' <<endl;
else{
//cout << pol.Point_in_polygon(p1) << ' ' << pol.Point_in_polygon(p2) << endl;
if( pol.Point_in_polygon(p1) && pol.Point_in_polygon(p2) ) cout << 'T' << endl;
else cout << 'F' <<endl;
}
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
struct node
{
int l,r,s;
}p[500];
int loc[500];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(cin >> n)
{
if( n == 0) break;
for(int i = 0 ; i < n ; i++) cin >> p[i].s;
for(int i = 0 ; i < n ; i ++)
{
int ll = 0;
for(int j = 0; j < i ; j ++)
ll = max(ll , p[j].r - abs( p[j].s - p[i].s ));
p[i].l =ll;
p[i].r = ll + 2 * p[i].s;
}
for(int i = 0 ; i < n ; i++)
{
int ml = p[i].l,mr = p[i].r;///重要
for(int j = 0; j < i ; j++)
ml = max(ml,p[j].r);
for(int j = i + 1; j < n ; j++)
mr = min(mr,p[j].l);
if( ml >= mr ) continue;
else cout << i + 1 << ' ';
}
cout << endl;
}
return 0;
}
3.5____线段与多边形判断相交
Intersection
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const double eps = 1e-8;
const double pi = acos( -1.0);
///Compares a double to zero
int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
///square of a double
inline double sqr(double x) { return x * x; }
/////////////////////////////////////////////////
struct Point
{
double x,y;
Point(){} ///no arguments constructor
Point(double _x,double _y) {
x = _x , y = _y; ///arguments constructor
}
bool operator == (Point b) const{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (Point b) const{
return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
}
///数量积
Point operator - (const Point &b) const{
return Point(x - b.x , y - b.y);
}
Point operator + (const Point &b) const{
return Point(x + b.x , y + b.y);
}
Point operator * (const double &k) const{
return Point(x * k , y * k );
}
Point operator / (const double &k) const{
return Point(x / k , y / k);
}
///叉积
double operator ^ (const Point &b) const{
return x * b.y - y * b.x;
}
///点积
double operator * (const Point &b) const{
return x * b.x + y * b.y;
}
///线段的长度
double len(){
return hypot(x,y); ///<cmath>
}
///长度的平方
double len2(){
return x * x + y * y;
}
///返回两点的距离
double distance(Point p){
return hypot( x - p.x , y - p.y );
}
};
struct Line
{
vector<char> croset;
char name;
Point s,e;
Line(){}
Line( Point _s, Point _e ){ s =_s ; e=_e; }
void input(Point _p1,Point _p2)
{
s = _p1,e = _p2;
}
///直线与线段相交判断
///-*this line -v seg
///2规范相交,1非规范相交,0不相交
bool linecrossseg(Line v){
return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
}
///点与直线关系
///1在左侧
///2在右侧
///3在直线
int relation(Point p){
int c = sgn( (p-s) ^ (e -s) );
if(c < 0) return 1;
else if(c > 0) return 2;
else return 3;
}
///点在线段上的判断
bool point_on_seg(Point p){
return sgn((p-s)^(e-s) ) == 0 && sgn( (p-s)*(p-e) ) <= 0 ;
}
///两向量平行(对应直线平行或重合)
bool parallel(Line v){
return sgn( (e-s)^( v.e - v.s ) ) == 0;
}
///两直线关系 0-平行,1-重合,2-相交
int linecrossline(Line v){
if( (*this).parallel(v) )
return v.relation(s) == 3;
return 2;
}
///得到交点,需先判断直线是否相交
Point crosspoint(Line v){
double a1 = ( v.e - v.s ) ^ ( s - v.s );
double a2 = ( v.e - v.s ) ^ ( e - v.s );
return Point( (s.x * a2 - e.x * a1)/(a2 - a1) , (s.y *a2 - e.y *a1)/(a2 - a1));
}
///两线段相交判断
///2 规范相交
///1 非规范相交
///0 不想交
int segcrossseg(Line v) {
int d1 = sgn((e - s) ^ (v.s - s));
int d2 = sgn((e - s) ^ (v.e - s));
int d3 = sgn((v.e - v.s) ^ (s - v.s));
int d4 = sgn((v.e - v.s) ^ (e - v.s));
if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2)return 2;
return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) ||
(d2 == 0 && sgn((v.e - s) * (v.e - e)) <= 0) ||
(d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) ||
(d4 == 0 && sgn((e - v.s) * (e - v.e)) <= 0);
}
};
struct polygon
{
int num; ///点的数量
Point p[4];
Line l[4];
struct cmp{
Point p;
cmp(const Point &p0){ p = p0;}
bool operator()( const Point &aa ,const Point &bb){
Point a = aa,b = bb;
int d = sgn( (a-p)^(b-p) );
if(d == 0) return sgn( a.distance(p) - b.distance(p)) < 0;
return d > 0;
}
};
/// 3在顶点上
/// 2在边上
/// 1在内部
/// 0在外面
int Point_in_polygon(Point tep)
{
for(int i = 0 ; i < num ; i++){
if( p[i] == tep ) return 3;
}
for(int i = 0 ; i < num ; i++){
if( l[i].point_on_seg(tep) ) return 2;
}
int tecnt = 0;
for(int i = 0 ; i < num ; i++)
{
int j = (i + 1) % num;
int c = sgn( (tep - p[j]) ^ (p[i] - p[j]) );
int u = sgn( p[i].y - tep.y );
int v = sgn( p[j].y - tep.y );
if( c > 0 && u < 0 && v >=0 ) tecnt ++;
if( c < 0 && u >= 0 && v < 0 ) tecnt --;
}
return tecnt != 0;
}
}pol;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t,n;
cin >> t;
while(t--)
{
Point p1,p2,j1,j3;
cin >> p1.x >> p1.y >> p2.x >> p2.y >> j1.x >> j1.y >> j3.x >> j3.y;
if( j1.x > j3.x ) swap(j1,j3);
Line lp(p1,p2);
Point j2,j4;
j2.x = j3.x,j2.y = j1.y,j4.x = j1.x ,j4.y = j3.y;
polygon pol;
pol.p[0] = j1;
pol.p[1] = j2;
pol.p[2] = j3;
pol.p[3] = j4;
pol.l[0].input(j1,j2);pol.l[1].input(j2,j3),pol.l[2].input(j3,j4),pol.l[3].input(j4,j1);
pol.num = 4;
bool flag = 0;
for(int i = 0; i < 4 ; i++)
if( lp.segcrossseg(pol.l[i]) > 0 ){
flag = 1;
break;
}
if( flag ) cout <<'T' <<endl;
else{
//cout << pol.Point_in_polygon(p1) << ' ' << pol.Point_in_polygon(p2) << endl;
if( pol.Point_in_polygon(p1) && pol.Point_in_polygon(p2) ) cout << 'T' << endl;
else cout << 'F' <<endl;
}
}
return 0;
}
3.6____计算凸包,周长
Surround the Trees
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const double pi = acos( -1.0);
///Compares a double to zero
int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
///square of a double
inline double sqr(double x) { return x * x; }
/////////////////////////////////////////////////
struct Point
{
double x,y;
Point(){} ///no arguments constructor
Point(double _x,double _y) {
x = _x , y = _y; ///arguments constructor
}
/*void input(){
scanf("%lf%lf",&x,&y);
}
void output(){
printf("%.2f %.2f
",x,y);
}*/
bool operator == (Point b) const{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator < (Point b) const{
return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
}
///数量积
Point operator - (const Point &b) const{
return Point(x - b.x , y - b.y);
}
Point operator + (const Point &b) const{
return Point(x + b.x , y + b.y);
}
Point operator * (const double &k) const{
return Point(x * k , y * k );
}
Point operator / (const double &k) const{
return Point(x / k , y / k);
}
///叉积
double operator ^ (const Point &b) const{
return x * b.y - y * b.x;
}
///点积
double operator * (const Point &b) const{
return x * b.x + y * b.y;
}
///线段的长度
double len(){
return hypot(x,y); ///<cmath>
}
///长度的平方
double len2(){
return x * x + y * y;
}
///返回两点的距离
double distance(Point p){
return hypot( x - p.x , y - p.y );
}
///计算 pa 和 pb 的夹角
double rad(Point a,Point b){
Point p = *this;
return fabs( atan2( fabs( (a-p)^(b-p) ) , (a-p)*(b-p) ) );
}
///化为长度为r的向量
Point trunc(double r){
double l = len();
if( !sgn(l) ) return *this;
}
///逆时针旋转90度
Point rotleft(){
return Point(y,-x);
}
///顺时针旋转90度
Point rotright(){
return Point(y,-x);
}
///绕着p点逆时针
Point rotata(Point p,double angle){
Point v = (*this) - p;
double c = cos(angle) , s = sin(angle);
return Point(p.x + v.x * c - v.y * s , p.y + v.x *s + v.y * c);
}
};
struct Line
{
Point s,e;
Line(){}
Line( Point _s, Point _e ){ s =_s ; e=_e; }
///由斜倾角angle与任意直线一点确定直线 y = kx + b;
void input( Point _s, Point _e ){ s =_s ; e=_e; }
Line(Point p,double angle){
s = p;
if( sgn(angle - pi/2) == 0 ) e = (s + Point(0,1));
else e = (s + Point(1,tan(angle)));
}
///ax + by + c = 0;
Line(double a,double b,double c){
if( sgn(a) == 0 )
{
s = Point(0,-c/b);
e = Point(1,-c/b);
}
else if(sgn(b) == 0)
{
s = Point(-c/a,0);
e = Point(-c/a,1);
}
else
{
s = Point(0,-c/b);
e = Point(1,(-c-a)/b);
}
}
///直线与线段相交判断
///-*this line -v seg
///2规范相交,1非规范相交,0不相交
bool linecrossseg(Line v){
return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
}
///点与直线关系
///1在左侧
///2在右侧
///3在直线
int relation(Point p){
int c = sgn( (p-s) ^ (e -s) );
if(c < 0) return 1;
else if(c > 0) return 2;
else return 3;
}
///点在线段上的判断
bool point_on_seg(Point p){
return sgn((p-s)^(e-s) ) == 0 && sgn( (p-s)*(p-e) ) <= 0 ;
}
///两向量平行(对应直线平行或重合)
bool parallel(Line v){
return sgn( (e-s)^( v.e - v.s ) ) == 0;
}
///两直线关系 0-平行,1-重合,2-相交
int linecrossline(Line v){
if( (*this).parallel(v) )
return v.relation(s) == 3;
return 2;
}
///得到交点,需先判断直线是否相交
Point crosspoint(Line v){
double a1 = ( v.e - v.s ) ^ ( s - v.s );
double a2 = ( v.e - v.s ) ^ ( e - v.s );
return Point( (s.x * a2 - e.x * a1)/(a2 - a1) , (s.y *a2 - e.y *a1)/(a2 - a1));
}
///两线段相交判断
///2 规范相交
///1 非规范相交
///0 不想交
int segcrossseg(Line v) {
int d1 = sgn((e - s) ^ (v.s - s));
int d2 = sgn((e - s) ^ (v.e - s));
int d3 = sgn((v.e - v.s) ^ (s - v.s));
int d4 = sgn((v.e - v.s) ^ (e - v.s));
if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2)return 2;
return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) ||
(d2 == 0 && sgn((v.e - s) * (v.e - e)) <= 0) ||
(d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) ||
(d4 == 0 && sgn((e - v.s) * (e - v.e)) <= 0);
}
};
struct triangle
{
Point A,B,C;
Line a,b,c;
triangle(){}
triangle(Point _A,Point _B,Point _C){ A = _A ; B = _B ; C = _C;}
///求重心
Point incenter(){
return Point( ( A.x + B.x + C.x ) / 3, ( A.y + B.y + C.y ) / 3);
}
};
const int maxp = 100;
const int maxl = 200;
struct polygon
{
int n; ///点的数量
Point p[maxp];
Line l[maxl];
struct cmp{
Point p;
cmp(const Point &p0){ p = p0;}
bool operator()( const Point &aa ,const Point &bb){
Point a = aa,b = bb;
int d = sgn( (a-p)^(b-p) );
if(d == 0) return sgn( a.distance(p) - b.distance(p)) < 0;
return d > 0;
}
};
///极角排序
///mi为最左下角的点
void norm(){
Point mi = p[0];
for(int i = 1; i < n; i ++) mi = min(mi,p[i]);
sort(p, p + n, cmp(mi) );
}
/// 判断任意点与多边形的关系
/// 3在顶点上
/// 2在边上
/// 1在内部
/// 0在外面
int Point_in_polygon(Point tep)
{
for(int i = 0 ; i < n ; i++){
if( p[i] == tep ) return 3;
}
for(int i = 0 ; i < n; i++){
if( l[i].point_on_seg(tep) ) return 2;
}
int tecnt = 0;
for(int i = 0 ; i < n ; i++)
{
int j = (i + 1) % n;
int c = sgn( (tep - p[j]) ^ (p[i] - p[j]) );
int u = sgn( p[i].y - tep.y );
int v = sgn( p[j].y - tep.y );
if( c > 0 && u < 0 && v >=0 ) tecnt ++;
if( c < 0 && u >= 0 && v < 0 ) tecnt --;
}
return tecnt != 0;
}
/// 得到凸包
/// 得到的凸包里的点编号是 0 ~ n-1 的
void getconvex(polygon &convex)
{
sort(p , p + n);
convex.n = n;
for(int i = 0 ; i < min(n,2) ; i++){
convex.p[i] = p[i];
}
///特判
if( convex.n == 2 && (convex.p[0] == convex.p[1]) ) convex.n--;
if( n <= 2) return;
int &top = convex.n;
top = 1;
for(int i = 2; i < n ; i++){
while(top && sgn( (convex.p[top] - p[i]) ^ (convex.p[top-1] - p[i])) <= 0 ) top --;
convex.p[++top] = p[i];
}
int temp = top;
convex.p[++top] = p[n-2];
for(int i = n - 3; i >=0 ; i--)
{
while( top!=temp && sgn( (convex.p[top] - p[i]) ^ (convex.p[top-1] - p[i]) ) <=0 ) top--;
convex.p[++top] = p[i];
}
if( convex.n == 2&& ( convex.p[0] == convex.p[1]) ) convex.n --; ///特判
convex.norm();///得到的是顺时针的点,排序后逆时针
}
///判断是不是凸多边形
bool isconvex(){
bool s[2];
memset(s,false,sizeof(s));
for(int i = 0 ; i < n ; i++){
int j = (i + 1) % n;
int k = (j + 1) % n;
s[ sgn((p[j] - p[i]) ^ (p[k]-p[i]) ) + 1] =true;
}
}
///得到周长
double getcircumference(){
double sum = 0;
for(int i = 0 ; i < n ; i++){
sum += p[i].distance( p[(i + 1)%n] );
}
return sum;
}
///得到面积
double getarea()
{
double sum = 0;
for(int i = 0; i < n ; i++){
sum += ( p[i]^p[ (i+1)%n ] );
}
return fabs(sum)/2;
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t,n;
while( true )
{
scanf("%d",&n);
if( n== 0) break;
polygon pol;
pol.n = n;
for(int i = 0; i < n ; i++) scanf("%lf %lf",&pol.p[i].x,&pol.p[i].y);
for(int i = 0 ; i <n ; i++) pol.l[i].input( pol.p[i] , pol.p[ (i + 1)%n ] );
polygon poly;
pol.getconvex(poly);
//printf("%d
",poly.n) ;
//printf("%.2f
",pol.getcircumference());
///如果只有两个点要特判,看计算凸包的公式就明白了
if( poly.n == 2 ) printf("%.2f
",poly.getcircumference()/2 );
else printf("%.2f
",poly.getcircumference() );
}
return 0;
}
3.7____平面几何
Keiichi Tsuchiya the Drift King
2018焦作——ICPC
#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1);
const double eps = 1e-8;
int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
scanf("%d",&t);
while(t--)
{
double a,b,d,r;
scanf("%lf%lf%lf%lf",&a,&b,&r,&d);
double delta = d * pi / 180.0;
double stand = atan( b/ (a+r) );
if( sgn( delta - stand ) >= 0 )
{
printf("%.12f
",sqrt( b*b + (a + r)*(a + r) ) - r);
}
else
{
double ans = sin(delta) * (b - (a+r)*tan(delta)) + (a+r)/cos(delta) - r;
printf("%.12f
",ans);
}
}
return 0;
}
3.8____最小圆覆盖
Buried memory
HDU_3007
#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1);
const double eps = 1e-8;
inline int sgn(double x)
{
if( fabs(x) < eps ) return 0;
if( x < 0 ) return -1;
else return 1;
}
int n;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){ x = _x;y=_y; }
}p[510];
inline double dis(Point a,Point b )
{
return hypot( a.x - b.x,a.y - b.y );
}
///求三角形外接圆圆心
inline Point circle_certer(const Point a,const Point b,const Point c)
{
Point center;
double a1 = b.x - a.x, b1 = b.y - a.y,c1 = (a1 * a1 + b1 * b1) / 2;
double a2 = c.x - a.x, b2 = c.y - a.y,c2 = (a2 * a2 + b2 *b2) / 2;
double d = a1 * b2 - a2 *b1;
center.x = a.x + (c1 * b2 - c2 *b1) /d;
center.y = a.y + (a1 * c2 - a2 *c1) /d;
return center;
}
void min_cover_circle(Point &c,double &r)
{
random_shuffle(p,p+n); ///将点的排列顺序随机化,降低枚举的时间复杂度
c = p[0],r = 0; ///从第一个点开始,
for(int i = 1; i < n ; i++ )
if( sgn( dis(p[i],c) - r ) > 0 ){ ///新的点,在原来那个圆的外面
c = p[i],r = 0;
for(int j = 0; j < i ; j++){ ///从新检查前面的点是否都在圆内
if( sgn( dis(p[j],c) - r ) > 0 ){ ///如果之前的点在新园的外面,从新定圆
c.x = (p[i].x + p[j].x ) /2;
c.y = (p[i].y + p[j].y ) /2;
r = dis( p[j],c );
for(int k = 0 ; k < j ; k ++){
if( sgn(dis(p[k],c) - r) > 0){///如果两点定的点不能满足,则选择3个点来确定
c = circle_certer(p[i],p[j],p[k]);
r = dis(p[i],c);
}
}
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while(~scanf("%d",&n) && n != 0)
{
Point ans;
double ansr;
for(int i =0 ; i < n ; i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
min_cover_circle(ans,ansr);
printf("%.2f %.2f %.2f
",ans.x,ans.y,ansr);
}
return 0;
}
3.9____空凸包(计算几何 + dp)
[Empty Convex Polygons](Empty Convex Polygons - HDU 6219 - Virtual Judge (vjudge.net))
ICPC_2017沈阳
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef double type_p;
const double eps = 1e-6;
const int maxn = 510;
double dp[maxn][maxn];
inline double eq(double x, double y) {
return fabs(x-y)<eps;
}
inline int eq(int x, int y) {
return x==y;
}
struct point {
type_p x,y;
};
type_p xmult(point a, point b, point o)
{
return (a.x-o.x)*(o.y-b.y)-(a.y-o.y)*(o.x-b.x);//b at ao left if negative, at right if positive
}
type_p dist(point a, point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
point o;
bool cmp_angle(point a,point b) {
if(eq(xmult(a,b,o),0.0)){
return dist(a,o)<dist(b,o);
}
return xmult(a,o,b)>0;
}
/*
Input: p: Point set
pn: size of the point set
Output: the area of the largest empty convex
*/
double empty_convex(point *p, int pn) {
double ans=0;
for(int i=0; i<pn; i++){
for(int j=0; j<pn; j++){
dp[i][j]=0;
}
}
for(int i=0; i<pn; i++){
int j = i-1;
while(j>=0 && eq(xmult(p[i], p[j], o),0.0))j--;//coline
bool flag= j==i-1;
while(j>=0){
int k = j-1;
while(k >= 0 && xmult(p[i],p[k],p[j])>0)k--;
double area = fabs(xmult(p[i],p[j],o))/2;
if(k >= 0)area+=dp[j][k];
if(flag) dp[i][j]=area;
ans=max(ans,area);
j=k;
}
if(flag){
for(int j=1; j<i; j++) {
dp[i][j] = max(dp[i][j],dp[i][j-1]);
}
}
}
return ans;
}
double largest_empty_convex(point *p, int pn) {
point data[maxn];
double ans=0;
for(int i=0; i<pn; i++) {
o=p[i];
int dn=0;
for(int j=0; j<pn; j++)
{
if(p[j].y>o.y||(p[j].y==o.y&&p[j].x>=o.x))
{
data[dn++]=p[j];
}
}
sort(data, data+dn, cmp_angle);
ans=max(ans, empty_convex(data, dn));
}
return ans;
}
int main() {
point p[110];
int t;
scanf("%d",&t);
while(t--) {
int pn;
scanf("%d",&pn);
for(int i=0; i<pn; i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
printf("%.1f
",largest_empty_convex(p,pn));
}
return 0;
}