您的位置:首页 > 其它

uvalive4838(凸包+重心)

2015-08-29 20:26 477 查看
题意:

给出一个n边形,我们要输出有多少种摆放方案使得这个多边形能够稳定摆放(如果重心落在边的端点上,不能稳固)。

思路:

用这n个点围成一个凸包,每次用凸包的一个边当做底边,判断重心是否落在这条边的端点上或者落在边的外面即可。

注意:一定要用初始的n边形求重心,不能用凸包求重心,因为这个我们WA了三个小时。

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=500005*2;
//const double pi=atan(1.0)*4;
const double eps = 1e-8;
int cmp(double x) {
if(fabs(x) < eps) return 0;
if(x > 0) return 1;
return -1;
}
struct node{
double x,y;
}e[maxn],res[maxn];
int cmp1(node a,node b)
{
if(cmp(a.x-b.x) == 0) return cmp(a.y-b.y) < 0;
return cmp(a.x-b.x)<0;
}
double cross(node a,node b,node c)//向量积
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
int convex(int n)//求凸包上的点
{
sort(e,e+n,cmp1);
int m=0,i,j,k;
for(i=0;i<n;i++)
{
while(m>1&&cmp(cross(res[m-1],e[i],res[m-2]))<=0)m--;
res[m++]=e[i];
}
k=m;
for(i=n-2;i>=0;i--)
{
while(m>k&&cmp(cross(res[m-1],e[i],res[m-2]))<=0)m--;
res[m++]=e[i];
}
if(n>1)m--;
return m;
}

struct point {
double x, y;
point() {};
point(double a, double b) : x(a), y(b) {};
friend point operator + (const point & a, const point &b) {
return point(a.x + b.x , a.y + b.y );
}
friend point operator - (const point & a, const point &b) {
return point(a.x - b.x, a.y - b.y);
}
friend point operator * (const point & a, const double &b) {
return point(a.x * b, a.y * b);
}
friend point operator / (const point & a, const double &b) {
return point(a.x / (b+eps), a.y / (b + eps));
}
};

double det(const point &a,const point &b) {
return a.x * b.y - a.y * b.x;
}

struct polygon {
int n;
point a[maxn];
polygon() {};
double area() {
//	    printf("nnnnnnnnnnnnnnnnnnnnnnnn%d\n", n);
double sum = 0;
a
= a[0];
for(int i = 0; i < n; i++) {
//            puts("JJJJJ");
sum += det(a[i + 1], a[i]);

}
return sum / 2;
}
point center() {
point ans = point(0, 0);
//		printf("a = %lf\n",area());
if(cmp(area()) == 0) return ans;
a
= a[0];
for(int i = 0; i < n; i++) {
ans = ans +(a[i] + a[i + 1]) * det(a[i + 1], a[i]);
}
return ans / area() / 6.0;
}
};

polygon p1;
polygon p2;
double dot(point a, point b) {
return a.x * b.x + a.y * b.y;
}
void PointPro(point p,point s,point t,point &cp) {
double r = dot((t - s),(p - s))/dot(t-s,t - s);
cp = s +  (( t - s) * r);
}

bool On(point p, point s, point t) {
if(cmp(p.x - s.x) == 0 && cmp(p.y - s.y) == 0) return false;
if(cmp(p.x - t.x) == 0 && cmp(p.y - t.y) == 0) return false;
return cmp(det(p-s, t - s)) == 0&& cmp(dot(p-s,p-t))<=0;
}

int main()
{
//    freopen("a.txt","r",stdin);
int T,n,l;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i = 0; i < n; i++){
cin >> e[i].x >> e[i].y;
//            e[i].x *= 1000;
//            e[i].y *= 1000;
p2.a[i]=point(e[i].x*1.0,e[i].y*1.0);
}
p2.n=n;
point p0 = p2.center();

int m=0;
m=convex(n);
//        if(m == 2) {
//            if(cmp(res[0].x - res[1].x) == 0 && cmp(res[0].y - res[1].y) == 0 ) {
//                printf("0\n");
//                continue;
//            }
//            else{
//                printf("2\n");
//                continue;
//            }
//        }
int _ans = 0;
p1.n = m;
//        printf("p1.n = %d\n", p1.n);
for(int i = 0; i < m; i++) {
p1.a[i] = point(res[i].x * 1.0 , res[i].y * 1.0 );
}
//        for(int i = 0; i < m; i++) {
//            printf("%lf %lf\n", p1.a[i].x , p1.a[i].y );
//        }
//        printf("p1.n = %d\n", p1.n);

//        printf("%lf %lf\n", p0.x, p0.y);
for(int i = 0; i < m; i++){
point jiaodian;
PointPro(p0, p1.a[i], p1.a[(i + 1) % m], jiaodian);
if(On(jiaodian, p1.a[i], p1.a[(i+1)%m])) {
_ans++;
}
//            printf("jiaod = %lf  %lf   %d\n", jiaodian.x, jiaodian.y,_ans);
}
printf("%d\n", _ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: