hdu3685 Rotational Painting 求多边形重心和凸包

http://acm.hdu.edu.cn/showproblem.php?pid=3685

Rotational Painting

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2614    Accepted Submission(s): 737


Problem Description
Josh Lyman is a gifted painter. One of his great works is a glass painting. He creates some well-designed lines on one side of a thick and polygonal glass, and renders it by some special dyes. The most fantastic thing is that it can generate different meaningful paintings by rotating the glass. This method of design is called “Rotational Painting (RP)” which is created by Josh himself. 

You are a fan of Josh and you bought this glass at the astronomical sum of money. Since the glass is thick enough to put erectly on the table, you want to know in total how many ways you can put it so that you can enjoy as many as possible different paintings hiding on the glass. We assume that material of the glass is uniformly distributed. If you can put it erectly and stably in any ways on the table, you can enjoy it. 

More specifically, if the polygonal glass is like the polygon in Figure 1, you have just two ways to put it on the table, since all the other ways are not stable. However, the glass like the polygon in Figure 2 has three ways to be appreciated. 

Pay attention to the cases in Figure 3. We consider that those glasses are not stable.
 

Input
The input file contains several test cases. The first line of the file contains an integer T representing the number of test cases. 

For each test case, the first line is an integer n representing the number of lines of the polygon. (3<=n<=50000). Then n lines follow. The ith line contains two real number x i and y i representing a point of the polygon. (x i, y i) to (x i+1, y i+1) represents a edge of the polygon (1<=i<n), and (x n,y n) to (x 1, y 1) also represents a edge of the polygon. The input data insures that the polygon is not self-crossed.
 

Output
For each test case, output a single integer number in a line representing the number of ways to put the polygonal glass stably on the table.
 

Sample Input
  
  
2 4 0 0 100 0 99 1 1 1 6 0 0 0 10 1 10 1 1 10 1 10 0
 

Sample Output
  
  
2 3
Hint
The sample test cases can be demonstrated by Figure 1 and Figure 2 in Description part.
 

Source

题意:给一个多边形,问有几种稳定的摆放方式。。

思路:很简单。。。求出多边形的重心,然后由于不一定是凸多边形,所以再求下多边形凸包,枚举凸包的每一条边,看重心做垂足是否在边上,注意题目要求垂足在端点不算。。可以用点积看夹角是不是锐角来判断垂足位置。。

/**
 * @author neko01
 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define clr(a) memset(a,0,sizeof a)
#define clr1(a) memset(a,-1,sizeof a)
#define dbg(a) printf("%d\n",a)
typedef pair<int,int> pp;
const double eps=1e-8;
const double pi=acos(-1.0);
const int INF=0x7fffffff;
const LL inf=(((LL)1)<<61)+5;
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    if(x>0) return 1;
    return -1;
}
struct point{
    double x,y;
    point(double x=0,double y=0):x(x),y(y) {}
};
point operator +(const point &a,const point &b){
	return point(a.x+b.x,a.y+b.y);
}
point operator -(const point &a,const point &b){
	return point(a.x-b.x,a.y-b.y);
}
point operator *(const point &a,const double &p){
	return point(a.x*p,a.y*p);
}
point operator /(const point &a,const double &p){
	return point(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);
}
bool operator == (const point &a,const point &b){
	return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double dot(point A,point B){
    return A.x*B.x+A.y*B.y;
}
double cross(point A,point B){
    return A.x*B.y-A.y*B.x;
}
double Length(point A){
    return sqrt(dot(A,A));
}
bool OnSegment(point p,point a1,point a2)   //判断点p是否在直线a1a2上
{
  return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<0; //线段包含端点时改成<=
}
point PolyGravity(point *p,int n)  //求多边形重心
{
    point ans=point(0,0);
    double sumArea=0,area;
    for(int i=2;i<n;i++)
    {
        area=cross(p[i-1]-p[0],p[i]-p[0]);
        sumArea+=area;
        ans.x+=(p[0].x+p[i-1].x+p[i].x)*area;
        ans.y+=(p[0].y+p[i-1].y+p[i].y)*area;
    }
    return ans/(sumArea*3);
}
int graham(point *p,int n,point *ch) //凸包
{
    sort(p,p+n);
    int m=0;
    for(int i=0;i<n;i++)
    {
        while(m>1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--)
    {
        while(m>k&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    if(n>1) m--;
    return m;
}
point p[50005];
point ch[50005];
bool check(point P,point A,point B)
{
    point v1=B-A,v2=P-A,v3=P-B;
    if(dcmp(dot(v1,v2))<=0) return false;
    if(dcmp(dot(v1,v3))>=0) return false;
    return true;
}
int main()
{
    int n,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        point g=PolyGravity(p,n);
        int m=graham(p,n,ch),ans=0;
        ch[m]=ch[0];
        for(int i=0;i<m;i++)
        {
            if(OnSegment(g,ch[i],ch[i+1])||check(g,ch[i],ch[i+1]))
                ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值