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. angularJS推荐显示注入写法

    使用js压缩工具时发现压缩之后的控制器注入参数由原来的$scope变成了a,b...这样的字母而导致js失效,那么我们推荐使用完整的显示注入方式来解决此问题! //隐式注入的写法 angular.mo ...

  2. Koala编译less

    下载地址:http://koala-app.com/index-zh.html 用Koala可以用来编译less,软件也是简单明了,平时开着其他软件编辑less,只要打开Koala,勾选“自动编译”后 ...

  3. 算法训练 Hanoi问题

      算法训练 Hanoi问题   时间限制:1.0s   内存限制:512.0MB      问题描述 如果将课本上的Hanoi塔问题稍做修改:仍然是给定N只盘子,3根柱子,但是允许每次最多移动相邻的 ...

  4. PHP运行错最有效解决办法Fatal error: Out of memory (allocated 786432) (tried to allocate 98304 bytes) in H:\freehost\zhengbao2\web\includes\lib_common.php on line 744

    原文 PHP运行错最有效解决办法Fatal error: Out of memory (allocated 6029312) Fatal error: Out of memory (allocated ...

  5. ArcGIS中利用ArcMap将地理坐标系转换成投影坐标系(从WKID=4326到WKID=102100)

    原文:ArcGIS中利用ArcMap将地理坐标系转换成投影坐标系(从WKID=4326到WKID=102100) 对于非地理专业的开发人员,对与这些生涩的概念,我们不一定都要了解,但是我们要理解,凡是 ...

  6. webView、scrollView、TableView,为了防止滚动时出现偏移,底部黑框问题等

    if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {self.automaticallyAd ...

  7. c#导出excel(转)

    C#导出Excel文件实例代码 2010-08-03 14:10:36|  分类: 软件编程 |  标签:excel  c#导出excel   |字号大中小 订阅 /// <summary> ...

  8. sql server 2008查询窗口怎么显示行数

    工具->选项

  9. 用Intellij IDEA 创建第一个maven项目!

    1. 一直想如何复用以前项目的maven的jar包! 其实只要拿到pom.xml即可!!! 1.1 创建一个maven项目 2. 3. 创建项目名和项目路径,我给项目起的名字是mavenV1.0 4. ...

  10. IDEA UML类图插件

    idea已经集成了该功能,只是默认没打开,仍然打开Settings界面,定位到Plugins,输入UML,参考下图: