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 xi and yi representing a point of the polygon. (xi,
yi) to (xi+1, yi+1) represents a edge of the polygon (1<=i<n), and (xn,yn) to (x1, y1) 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

2010 Asia Hangzhou Regional Contest

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

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

/**
 * @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;
}
时间: 2024-10-13 10:17:15

hdu3685 Rotational Painting 求多边形重心和凸包的相关文章

Hdu 3685 Rotational Painting(多边形重心+凸包)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3685 思路:先求出多边形重心,放置的边一定为凸包边.判断重心是否落在边之间(求点到直线与点到线段的距离,判断). 4 0 0 4 0 8 4 4 4 注意这种情况,重心不能在凸包边端点的垂线上. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using name

UVALive 4426 Blast the Enemy! --求多边形重心

题意:求一个不规则简单多边形的重心. 解法:多边形的重心就是所有三角形的重心对面积的加权平均数. 关于求多边形重心的文章: 求多边形重心 用叉积搞一搞就行了. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #define Mod 100000000

hdu1115 Lifting the Stone(几何,求多边形重心模板题)

题意:就是给你一个多边行的点的坐标,求此多边形的重心. 一道求多边形重心的模板题! #include<cstdio> #include<cmath> #include<cstring> using namespace std; struct point { double x,y; }PP[1000047]; point bcenter(point pnt[],int n){ point p,s; double tp,area = 0, tpx=0, tpy=0; p.x

hdoj-1115-Lifting the Stone 求多边形重心问题

Lifting the Stone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6329 Accepted Submission(s): 2624 Problem Description There are many secret openings in the floor which are covered by a big heavy

HDU 1115(求质量均匀分布的多边形重心 物理)

题意是给一个 n 边形,给出沿逆时针方向分布的各顶点的坐标,求出 n 边形的重心. 求多边形重心的情况大致上有三种: 一.多边形的质量都分布在各顶点上,像是用轻杆连接成的多边形框,各顶点的坐标为Xi,Yi,质量为mi,则重心坐标为: X = ∑( xi * mi ) /  ∑ mi ; Y = ∑( yi * mi)  / ∑ mi; 若每个顶点的质量相等,则重心坐标为: X = ∑ xi / n; Y = ∑ yi / n; 二.多边形的质量分布均匀,像是用密度相同的材料制成的多边形板子,多采

hdu 1115(计算多边形重心)

题意:已知一多边形没有边相交,质量分布均匀.顺序给出多边形的顶点坐标,求其重心. 分析: 求多边形重心的题目大致有这么几种: 1,质量集中在顶点上.n个顶点坐标为(xi,yi),质量为mi,则重心 X = ∑( xi×mi ) / ∑mi Y = ∑( yi×mi ) / ∑mi 特殊地,若每个点的质量相同,则 X = ∑xi / n Y = ∑yi / n 2,质量分布均匀.这个题就是这一类型,算法和上面的不同. 特殊地,质量均匀的三角形重心: X = ( x0 + x1 + x2 ) / 3

hdu 1115(多边形重心问题)

Lifting the Stone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6971    Accepted Submission(s): 2919 Problem Description There are many secret openings in the floor which are covered by a big

hdu 3685 10 杭州 现场 F - Rotational Painting 重心

F - Rotational Painting Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3685 Appoint description:  System Crawler  (2014-11-09) Description Josh Lyman is a gifted painter. One of his great works

hdu 3685 多边形重心+凸包

Rotational Painting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2498    Accepted Submission(s): 702 Problem Description Josh Lyman is a gifted painter. One of his great works is a glass pain