计算几何

如何证明一个四边形是凹四边形

题目描述

如何证明一个四边形是凹四边形

计算几何


算法1

用AC在直线BD的一侧来证明是凹四边形

C++ 代码

const int N=2e5+10;
int n,m,k,a[N],b[N];
int x[N],y[N];
int val(int i,int j,int k){
	return (y[j]-y[k])*(x[i]-x[k])+(y[k]-y[i])*(x[j]-x[k]);
}
void solve(){
	//try it again.
	up(1,4)cin>>x[o]>>y[o];
	if(val(1,2,4)*val(3,2,4)>0)NO
	if(val(2,1,3)*val(4,1,3)>0)NO
	YES
}

算法2

(用BC在直线AD的两侧来证明是凹四边形

C++ 代码

const int N=2e5+10;
int n,m,k,a[N],b[N];
int x[N],y[N];
int val(int i,int j,int k){
	return (y[j]-y[k])*(x[i]-x[k])+(y[k]-y[i])*(x[j]-x[k]);
}
void solve(){
	//try it again.
	up(1,4)cin>>x[o]>>y[o];
	if(val(1,2,3)*val(4,2,3)<0)NO
	if(val(2,1,4)*val(3,1,4)<0)NO
	YES
}

E 鸡算几何 (计算几何)

链接:E-鸡算几何_2023牛客寒假算法基础集训营1 (nowcoder.com)

in

4
0 1 0 0 1 0
1.000000000 0.000000000 0.000000000 0.000000000 0.000000000 1.000000000
1 0 0 0 0 2
2.000000000 0.000000000 0.000000000 0.000000000 0.000000000 1.000000000
45 67 0 0 26 -24
3.021000000 47.390000000 -41.979000000 -19.610000000 -74.030581210 -4.620132023
50 -58 0 0 65 88
75.106000000 -9.735000000 25.106000000 48.265000000 -71.510643929 -3.059693042

out

NO
YES
YES
YES

说明

具体来说,二维平面上有一根(L)型的铁丝,由AB和BC两条线段组成,鸡可以用以下三种操作玩铁丝:

1、在平面内任意地平移铁丝,即铁丝上每一个点横坐标都变化(Delta x)、纵坐标都变化(Delta y)

2、以B点为轴,任意地旋转铁丝,旋转是在平面上进行的(即旋转过程中铁丝不能离开地面);

3、鸡是三维生物!鸡将该铁丝拿起,在自己手里任意的调整铁丝的姿态后(鸡不能使铁丝发生形变)再随意放回平面上任意位置。

鸡可以任意(任意顺序、任意次数、不同的操作可以交替使用)使用上述三种操作来操作铁丝,经过一段时间的操作后,得到新铁丝的位置可以用线段DE和EF描述。注意DE并不保证与AB对应,EF同理,即DEF只描述操作后铁丝的形状。

现在,你想知道只根据ABC与DEF的信息,是否可以断言鸡一定使用过至少一次第三种操作。

可以看出,操作3能做到而操作1+2做不到的,就是将铁丝进行沿AB或

BC的翻转(例如A变为关于BC的对称点),这可以使用叉乘来判断;

具体来说,首先将AB、BC和ED、EF按照长度进行匹配,找到ABC与DEF

的关系,假设ABC与DEF一一对应,则cross(AB,BC)与cross(DE,EF)

正负性不同时,说明一定进行了操作3,cross为叉乘;

特别的,AB和BC长度相等时无法判断,总是no;

若遇到精度问题,考虑比较AB和BC长度时使用整数而非浮点数比较;

或在ABC和DEF进行匹配时使用较大的eps(如1e-5,注意这里使用较

小的如1e-9等eps反而可能炸)

这道题用到了叉乘的板子,在下面贴一下

T cross(const Point &a, const Point &b) {
    return a.x * b.y - a.y * b.x;
}

这个嘛就是叉乘的板子hhh

将叉乘和这个题结合讲一下

image-20230117171204350

key code

using T = double;
struct Point {
    T x;
    T y;
    Point(T x = 0, T y = 0) : x(x), y(y) {}
      
    Point &operator+=(const Point &p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point &operator-=(const Point &p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point &operator*=(const T &v) {
        x *= v, y *= v;
        return *this;
    }
    friend Point operator-(const Point &p) {
        return Point(-p.x, -p.y);
    }
    friend Point operator+(Point lhs, const Point &rhs) {
        return lhs += rhs;
    }
    friend Point operator-(Point lhs, const Point &rhs) {
        return lhs -= rhs;
    }
    friend Point operator*(Point lhs, const T &rhs) {
        return lhs *= rhs;
    }
};
  
T dot(const Point &a, const Point &b) {
    return a.x * b.x + a.y * b.y;
}
  
T cross(const Point &a, const Point &b) {
    return a.x * b.y - a.y * b.x;
}
 
const int N=2e5+10;
void solve(){
    //try it again.
    Point a[6];
    up(0,5)cin>>a[o].x>>a[o].y;
    if(cross(a[0]-a[1],a[2]-a[1])<0)swap(a[0],a[2]);
    if(cross(a[3]-a[4],a[5]-a[4])<0)swap(a[3],a[5]);
    db len0=sqrt(dot(a[0]-a[1],a[0]-a[1]));
    db len1=sqrt(dot(a[3]-a[4],a[3]-a[4]));
    if(abs(len0-len1)>1e-9)YES
    NO
}

E-公平守望的灯塔

E-公平守望的灯塔_2023牛客寒假算法基础集训营3 (nowcoder.com)

小红在平面直角坐标系上选择了两个点(A)(B)(保证两点不重合),它们的坐标分别为((x_A,y_A))((x_B,y_B))。小红希望你选择一个整点(C),满足三角形(ABC)为以(AB)为斜边的等腰直角三角形。你能帮帮她吗?
整点的定义:横坐标和纵坐标均为整数。

输入描述:

四个整数(x_A,y_A,x_B,y_B),用空格隔开。
$ -10^9leq x_A,y_A,x_B,y_B leq 10^9$

输出描述

如果无解,请直接输出"No Answer!"
否则输出两个整数(x_C,y_C),代表(C)点的坐标。有多解时输出任意即可。

in

1 0 0 1

out

0 0

这个题可以套用一下板子

先求出对应的两个点,再看这两个点满不满足题意

因为我们知道double 的答案应该怎么求

然后再强转成int型

如果强转以后仍然满足条件

那么就是成立的

key code

using T = long long;
struct Point {
    T x;
    T y;
    Point(T x = 0, T y = 0) : x(x), y(y) {}
     
    Point &operator+=(const Point &p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point &operator-=(const Point &p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point &operator*=(const T &v) {
        x *= v, y *= v;
        return *this;
    }
    friend Point operator-(const Point &p) {
        return Point(-p.x, -p.y);
    }
    friend Point operator+(Point lhs, const Point &rhs) {
        return lhs += rhs;
    }
    friend Point operator-(Point lhs, const Point &rhs) {
        return lhs -= rhs;
    }
    friend Point operator*(Point lhs, const T &rhs) {
        return lhs *= rhs;
    }
}p[4];
 
T dot(const Point &a, const Point &b) {
    return a.x * b.x + a.y * b.y;
}
 
T cross(const Point &a, const Point &b) {
    return a.x * b.y - a.y * b.x;
}
void solve(){
	//try it again.
	int A,B,C,D;
	cin>>A>>B>>C>>D;
	p[0].x=A;p[0].y=B;
	p[2].x=C;p[2].y=D;
	p[1].x =((p[0].x+p[2].x)+(p[2].y-p[0].y))/2;
	p[1].y =((p[0].y+p[2].y)+(p[0].x-p[2].x))/2;
	p[3].x =((p[0].x+p[2].x)-(p[2].y-p[0].y))/2;
	p[3].y =((p[0].y+p[2].y)-(p[0].x-p[2].x))/2;
	if(dot(p[1]-p[0],p[1]-p[3])==0){
		cout<<p[1].x<<" "<<p[1].y<<endl;
	}
	else if(dot(p[3]-p[0],p[2]-p[3])==0){
		cout<<p[3].x<<" "<<p[3].y<<endl;
	}
	else cout<<"No Answer!";
}

原文链接: https://www.cnblogs.com/liangqianxing/p/17047750.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    计算几何

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/311517

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月16日 下午12:01
下一篇 2023年2月16日 下午12:01

相关推荐