计算几何求公式

24 篇文章 0 订阅
5 篇文章 0 订阅

例题1:POJ 1380(矩阵的包含),给你两个矩阵的长和宽,问前面这个矩阵能否包含后面这个矩阵。

(1)、当前面的矩阵的宽<小于后面这个矩阵的宽时,不能包含。

(2)、当前面矩阵的面积<=后面矩阵的面积,不能包含。

(3)、当前面矩阵的长,宽>后矩阵的长,宽,能够包含。

(4)、特别注意前矩阵宽>后矩阵的宽,但是长<后矩阵的长。如图,可能会包含。

 

判断只需要后面这个矩阵在水平方向上的投影之和<=前面这个矩阵的长。sin∠1=B/sqrt(C*C+D*D),∠1和∠2之间的那个角的正弦值=D/sqrt(C*C+D*D),水平方向的投影和为:

C*cos∠2+D*sin∠2,自己认真看看,具体见代码。

#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int main()
{   double A,B,C,D;
    int Case;
    cin>>Case;
    while(Case--)
    {   cin>>A>>B>>C>>D;
        if(A<B) swap(A,B);
        if(C<D) swap(C,D);
        if(B<D||A*B<=C*D) puts("Box cannot be dropped.");
        else if(A>C&&B>D) puts("Escape is possible.");
        else 
        {   double Dis=sqrt(C*C+D*D);
            double a=asin(B/Dis),b=asin(D/Dis);
            if(C*cos(a-b)+D*sin(a-b)<=A) puts("Escape is possible.");
            else puts("Box cannot be dropped.");   
        }
    }
    return 0;    
}

例题2:湖南省第六届程序设计竞赛第四题:

描述

在平面直角坐标系下,台球桌是一个左下角在(0,0),右上角在(L,W)的矩形。有一个球心在(x,y),半径为R的圆形母球放在台球桌上(整个球都在台球桌内)。受撞击后,球沿极角为a的射线(即:x正半轴逆时针旋转到此射线的角度为a)飞出,每次碰到球桌时均发生完全弹性碰撞(球的速率不变,反射角等于入射角)。

如果球的速率为vs个时间单位之后球心在什么地方?

输入

输入文件最多包含25组测试数据,每个数据仅一行,包含8个正整数L,W,x,y,R,a,v,s(100<=L,W<=105, 1<=R<=5,R<=x<=L-R, R<=y<=W-R, 0<=a<360, 1<=v,s<=105),含义见题目描述。L=W=x=y=R=a=v=s=0表示输入结束,你的程序不应当处理这一行。

输出

对于每组数据,输出仅一行,包含两个实数x, y,表明球心坐标为(x,y)。xy应四舍五入保留两位小数。

样例输入

100 100 80 10 5 90 2 23
110 100 70 10 5 180 1 9999
0 0 0 0 0 0 0 0

样例输出

80.00 56.00
71.00 10.00

分析:将速度方向分解为水平方向的V1=Vcosa,和垂直方向的V2=Vsina。由于是完全弹性碰撞,所以在每个方向的速度大小不变,做匀速直线运动。可以求出每个方向的总长度。
                                                                

 

假设经过单位时间s后水平方向的位置变为len1,如果超过X=L-R,这个时候我们应该将这点转移到桌子内部,直接将超出的部分以X=L-R为对称轴求出对称点即可。这个时候位置变为:2(L-R)-len1。反之要是len1<R,这应该以X=R为对称轴将点转移到桌子内部。此时位置变为2R-len1,一直循环知道最终的结果在(R,L-R)即可输出。

垂直方向的分析一样,具体见代码:

#include<iostream>
#include<cmath>
#include<iomanip> 
using namespace std;
#define pi acos(-1.0)
struct Point
{   int x,y;
    friend istream& operator>>(istream &cin,Point &P)
    {   cin>>P.x>>P.y;
    } 
    bool operator==(const int &n) const
    {   return x==n&&y==n;
    }
};
int main()
{   Point S;
    int L,W,R,a,v,s;
    while(cin>>L>>W>>S>>R>>a>>v>>s)  
    {   if(L==0&&W==0&&S==0&&R==0&&a==0&&v==0&&s==0) break;
        double v1,v2;
        v1=v*cos(a*pi/180); //水平方向速度 
        v2=v*sin(a*pi/180); //垂直方向速度   
        double len1,len2;
        len1=S.x+v1*s;
        len2=S.y+v2*s; 
        while(len1<=R||len1>=L-R)
        {   if(len1<=R) len1=2*R-len1;
            if(len1>=L-R) len1=2*(L-R)-len1;
        }
        while(len2<=R||len2>=W-R)
        {   if(len2<=R) len2=2*R-len2;
            if(len2>=W-R) len2=2*(W-R)-len2; 
        }
        cout.precision(2);
        cout<<fixed<<len1<<" "<<len2<<endl; 
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值