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.
 
题目大意:给一个简单多边形,问有多少种方法可以把这个多边形竖直稳定地放在一个平面上,如图所示。
思路:物理学告诉我们,要解决这个问题,首先要求出这个多边形质心,然后枚举每一种放法,看质心到地板的垂线是否在底边之间。
令G(i) = cross(p[i], p[i+1]), 质心为t,多边形的点集为p,cross为叉积。
那么t.x = sum(cross(p[i], p[i+1]) / 2 * (p[i].x + p[i + 1].x) / 3) / sum(cross(p[i], p[i+1]) / 2)
t.y = sum(cross(p[i], p[i+1]) / 2 * (p[i].y + p[i + 1].y) / 3) / sum(cross(p[i], p[i+1]) / 2)
这里不证明。
然后在不考虑稳定的情况下,多边形的放法显然取决于这个多边形的凸包的边数。
枚举凸包的每一条边,判断质心到地板的垂线的垂足是否在凸包的那条边之中。
若质心为O,底边的两点分别为A、B,那么垂足在AB上当且仅当∠OAB和∠OBA都为锐角。
那么向量AO和向量AB的点积为正数,那么∠OAB为锐角,∠OBA同理。
此题解决。
 
代码(281MS):
 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL; const int MAXN = ;
const double EPS = 1e-; inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} struct Point {
double x, y;
Point(double x = , double y = ): x(x), y(y) {}
void read() {
scanf("%lf%lf", &x, &y);
}
Point operator + (const Point &rhs) const {
return Point(x + rhs.x, y + rhs.y);
}
Point operator - (const Point &rhs) const {
return Point(x - rhs.x, y - rhs.y);
}
double operator * (const Point &rhs) const {
return x * rhs.x + y * rhs.y;
}
Point operator / (const double &rhs) const {
return Point(x / rhs, y / rhs);
}
bool operator < (const Point &rhs) const {
if(y != rhs.y) return y < rhs.y;
return x < rhs.x;
}
};
typedef Point Vector; double cross(const Point &a, const Point &b) {
return a.x * b.y - a.y * b.x;
} double cross(const Point &sp, const Point &op, const Point &ep) {
return cross(sp - op, ep - op);
} void Graham_scan(Point *p, int n, int *stk, int &top) {
sort(p, p + n);
top = ;
stk[] = ; stk[] = ;
for(int i = ; i < n; ++i) {
while(top && cross(p[stk[top - ]], p[stk[top]], p[i]) <= ) --top;
stk[++top] = i;
}
int len = top;
stk[++top] = n - ;
for(int i = n - ; i >= ; --i) {
while(top != len && cross(p[stk[top - ]], p[stk[top]], p[i]) <= ) --top;
stk[++top] = i;
}
} Point barycenter(Point *p, int n) {
double area = ;
Point res;
for(int i = ; i < n; ++i) {
double t = cross(p[i], p[i + ]) / ;
res.x += t * (p[i].x + p[i + ].x) / ;
res.y += t * (p[i].y + p[i + ].y) / ;
area += t;
}
return res / area;
} Point p[MAXN];
int stk[MAXN], top;
int n, T; int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = ; i < n; ++i) p[i].read();
p[n] = p[];
Point O = barycenter(p, n);
Graham_scan(p, n, stk, top); int ans = ;
for(int i = ; i < top; ++i) {
Point &A = p[stk[i]], &B = p[stk[i + ]];
ans += (sgn((O - A) * (B - A)) > && sgn((O - B) * (A - B)) > );
}
printf("%d\n", ans);
}
}

HDU 3685 Rotational Painting(多边形质心+凸包)(2010 Asia Hangzhou Regional Contest)的更多相关文章

  1. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

  2. HDU 3689 Infinite monkey theorem(DP+trie+自动机)(2010 Asia Hangzhou Regional Contest)

    Description Could you imaging a monkey writing computer programs? Surely monkeys are smart among ani ...

  3. HDU 3695 / POJ 3987 Computer Virus on Planet Pandora(AC自动机)(2010 Asia Fuzhou Regional Contest)

    Description Aliens on planet Pandora also write computer programs like us. Their programs only consi ...

  4. HDU 3721 Building Roads (2010 Asia Tianjin Regional Contest) - from lanshui_Yang

    感慨一下,区域赛的题目果然很费脑啊!!不过确实是一道不可多得的好题目!! 题目大意:给你一棵有n个节点的树,让你移动树中一条边的位置,即将这条边连接到任意两个顶点(边的大小不变),要求使得到的新树的直 ...

  5. HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)

    Description You are given an undirected graph with N vertexes and M edges. Every vertex in this grap ...

  6. HDU 3698 Let the light guide us(DP+线段树)(2010 Asia Fuzhou Regional Contest)

    Description Plain of despair was once an ancient battlefield where those brave spirits had rested in ...

  7. HDU 3697 Selecting courses(贪心+暴力)(2010 Asia Fuzhou Regional Contest)

    Description     A new Semester is coming and students are troubling for selecting courses. Students ...

  8. HDU 3699 A hard Aoshu Problem(暴力枚举)(2010 Asia Fuzhou Regional Contest)

    Description Math Olympiad is called “Aoshu” in China. Aoshu is very popular in elementary schools. N ...

  9. HDU 3696 Farm Game(拓扑+DP)(2010 Asia Fuzhou Regional Contest)

    Description “Farm Game” is one of the most popular games in online community. In the community each ...

随机推荐

  1. 支持4G以上文件的MD5单元

    根据网上一个流传很久的基于Delph4的MD5单元修改的, 可以支持4G以上的文件, 可以支持UNICODE字符的Delphi 恩.......对于大文件速度稍微慢了一点点, 在我自己的电脑上测试, ...

  2. 设计模式:建造者模式(Builder)

    定   义:将一个复杂对象的构建与它的表示分离,使得同一构建过程可以创建不同的表示. 结构图: 产品类: class Product { //部件集合 List<string> parts ...

  3. (转帖) java内存分配分析/栈内存、堆内存

    http://blog.csdn.net/qh_java/article/details/9084091

  4. H5 -- 本地存储计数器的值 和前端校验用户

    1. 存储计数器的值 <!DOCTYPE html> <html> <head lang="en"> <meta charset=&quo ...

  5. @MyBatis中的if...else...

    <select id="selectSelective" resultMap="xxx" parameterType="xxx"> ...

  6. URL Routing

    们知道在ASP.NET Web Forms中,一个URL请求往往对应一个aspx页面,一个aspx页面就是一个物理文件,它包含对请求的处理. 而在ASP.NET MVC中,一个URL请求是由对应的一个 ...

  7. Web:AJAX的详解

    Web中的AJAX技术: 1.介绍:全称:Asnchronous JavaScript and XML,即异步的JavaScript和XML功能:它不是某种编程语言,是一种无需加载整个网页的情况下能够 ...

  8. SqlServer基础:约束

    为了减少输入错误和保证数据库数据的完整性,可以对字段设置约束,例如考试成绩,其范围应该为0-100.约束是为了保证数据的完整性而实现的一套机制,约束包括:主键约束.外键约束.Unique约束.Chec ...

  9. [BS-06] 设置release发布时NSLog不打印设置

    设置release发布时NSLog不打印设置 前提:在XCode做开发调试时往往需要打印一些调试信息做debug用,大家知道当打印信息的地方多了之后在模拟器上跑可能不会有什么问题,因为模拟器用的是电脑 ...

  10. Android 百度地图SDK 定位

    引用locSDK_6.1.3.jar,切记添加相应的so文件. 1.定位初始化,需要使用getApplicationContext() mLocClient = new LocationClient( ...