题意
给你一个斜坡(从左往右,斜率越来越大),再给你一个多边形,再给你一个重心,然后问你最后这个多边形的重心会在哪里,假设地面摩擦力无穷大,且运动过程中重心必须时刻保持向下。
题解
我们先考虑一下简单的情况就是多边形往左边滚(即逆时针旋转)
设支撑点为q,重心为g,旋转角度为k
那么我们得满足什么条件呢
cos(angle(g-q))<=0
如何确定选择的角度呢?二分就行了,判断条件就是
1.我们把这个多边形围绕q点选择后,所有的点都在斜面的上面
2.cos(angle(g-q)+k)<=0
这样好像就行了
但是要注意一些坑点的就是可能会往右边滚,所以分一些情况就行了
代码
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
const double eps=1e-10;
const double eps2=1e-13;
const double PI=acos(-1.0);
struct Point{
double x,y;
Point(double x=0,double y=0):x(x),y(y){
}
};
typedef Point Vector;
Vector operator -(Point a,Point b){
return Vector(a.x-b.x,a.y-b.y);
}
Vector operator +(Point a,Point b){
return Vector(a.x+b.x,a.y+b.y);
}
Vector operator *(Vector a,double p){
return Vector(a.x*p,a.y*p);
}
Vector operator /(Vector a,double p){
return Vector(a.x/p,a.y/p);
}
bool operator <(const Point& a,const Point& b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);//在有精度需求,比如使用lower_bound的时候,加上dcmp()
}
int dcmp(double x){
if(fabs(x)<eps)return 0;
if(x<0)return -1;
return 1;
}
bool operator ==(const Point& a,const Point& b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Vector a,Vector b){
return a.x*b.x+a.y*b.y;
}//点积
double Cross(Vector a,Vector b){
return a.x*b.y-a.y*b.x;
}//叉积
double Length(Vector a){
return sqrt(Dot(a,a));
}//长度
//返回逆时针旋转90度的单位法向量;
Vector Normal(Vector a){
double l=Length(a);
return Vector(-a.y/l,a.x/l);
}
//返回向量夹角,无方向
double Angle(Vector a,Vector b){
return acos(Dot(a,b)/Len