kAri448. 游戏-点乘的运用
时间限制 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;
}