kAri448. 游戏-点乘的运用

5 篇文章 0 订阅
时间限制 1000 ms  内存限制 65536 KB

题目描述

小弱发明了一个好玩的游戏,游戏开始时给你一个凸多边形,这个多边形可以任意旋转,平移。让你造出一个正方形“容器”(足够大),容器的两边垂直,两边水平。用这个容器把这个多边形完全包含,且多边形有且只有一条边恰好与容器下边界重合(与外界相通),不同的边与外界相通代表不同的方案。现在让你判断是否有方案可以让这个多边形能够不掉下来。不掉下来要求是至少有一条边与容器之间存在压力(假设摩擦系数无穷大)。
如下图,左边会掉下来,右边不会掉下来。

输入格式

有多组数据。
对于每组数据,第一行是多边形点数n(3 <= n <= 1000),后面n行分别是这些点沿着多边形逆时针的二维坐标(xi, yi)(xi,yi的绝对值 <= 1000,输入数据精度精确到两位)。

输出格式

对每组数据输出有多少种方案可以使多边形不掉下来。

输入样例

3
0.00 0.00
2.00 0.00
1.00 1.00
3 
0.00 0.00
1.00 0.00
2.00 1.00
4
0.00 0.00
4.00 0.00
3.00 2.00
1.00 2.00

输出样例

0
2
3

额,怎么说呢,首先,要思考如何才能不掉出去:当一条边的两个角不同时<=90度的时候,他就没法掉出去,

Q:如何判断这两个角是不是满足条件?

对三个点 1(x[1],y[1]) , 2(x[2],y[2]), 3(x[3],y[3]),求角度2(射线21和射线23的夹角);

我觉得我们要有这样一个思想:

任何几何在程序中必须化为代数,并且少用除法以及复杂计算以减少误差。

求解一个角度是锐角还是钝角还是直角最好的判断就是点乘!一开始怎么没想到呢,唉,白交三次,用什么acos,atan神马的,符号特别难搞。。。   

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#define MAXN 1003
int sq[MAXN];
int main()
{
    double x[4],y[4];
    int flag=0,get=0;
    int i,j,n;
    double x_2,y_2;
    double a,b,aa,bb;
    while(scanf("%d",&n)!=EOF){
        scanf("%lf%lf",&x[1],&y[1]);
        scanf("%lf%lf",&x[2],&y[2]);
        scanf("%lf%lf",&x[3],&y[3]);
 
        x[0]=x[1];y[0]=y[1];
        x_2=x[2];y_2=y[2];
 
        for(i=2; i<=n+1;i++){
 
            a=x[1]-x[2];b=y[1]-y[2];
 
            aa=x[3]-x[2];bb=y[3]-y[2];
 
            if(a*aa+b*bb>=0){
                sq[i]=1;
            }
            else{
                sq[i]=0;
            }
//printf("sq[%d]=%d\n",i,sq[i]);
            x[1]=x[2];y[1]=y[2];
            x[2]=x[3];y[2]=y[3];
            if(i==n-1){
                x[3]=x[0];y[3]=y[0];
                continue;
            }
            if(i==n){
                x[3]=x_2;y[3]=y_2;
                continue;
            }
            if(i==n+1){
                    sq[1]=sq[i];
                    break;
            }
            scanf("%lf%lf",&x[3],&y[3]);
        }
        for(i=1;i<=n;i++){
            if(sq[i]==1){
                if(i==n){
                    i=0;flag=1;
                }
                if(sq[i+1]==1){
                    get++;
                }
            }
            if(flag){
                break;
            }
        }
        printf("%d\n",n-get);
        get=0;flag=0;
    }
    return 0;
}

     
     
    
    
   
   

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值