POJ 3246:Game 题解 (凸包)
2017-08-12 15:21
435 查看
题目链接:http://poj.org/problem?id=3246
题目大意:给你N个点,首先求出这N个点构成的凸包,然后对凸包中的每个点,求除去这个点后剩下N-1个点重新构成的凸包的最小面积。
代码测试情况:AC Memory:1804K Time:297ms
解题分析:将点集按照x->y的顺序排序,然后构造一个函数求点集中一定下标范围内的点的上半个或下半个凸包。首先求出整个凸包及面积S,然后对于凸包上的每个点x1,对其在凸包上相邻的两个点(x2,x3)的在点集中的下标范围中的点求上半或下半凸包面积S’(此时忽略该中间点),然后新的凸包面积Snew=S-(x2-x1)×(x3-x1)+S’。除去排序外复杂度为O(N)。另外对凸包S中的左下点和右上点要单独计算凸包。
题目大意:给你N个点,首先求出这N个点构成的凸包,然后对凸包中的每个点,求除去这个点后剩下N-1个点重新构成的凸包的最小面积。
代码测试情况:AC Memory:1804K Time:297ms
解题分析:将点集按照x->y的顺序排序,然后构造一个函数求点集中一定下标范围内的点的上半个或下半个凸包。首先求出整个凸包及面积S,然后对于凸包上的每个点x1,对其在凸包上相邻的两个点(x2,x3)的在点集中的下标范围中的点求上半或下半凸包面积S’(此时忽略该中间点),然后新的凸包面积Snew=S-(x2-x1)×(x3-x1)+S’。除去排序外复杂度为O(N)。另外对凸包S中的左下点和右上点要单独计算凸包。
#include<cstdio> #include<vector> #include<algorithm> #include<cmath> #include<string.h> using namespace std; typedef long long ll; typedef pair<int,int> P; #define fi first #define se second #define vec vector const double eps=1e-6; const int inf=0x3f3f3f3f; #define N int(1e5+5) vec<P> a; int n; double cp(int x1,int x2,int x3,int x4){//cross product P c=P(a[x2].fi-a[x1].fi,a[x2].se-a[x1].se); P b=P(a[x4].fi-a[x3].fi,a[x4].se-a[x3].se); return b.fi*c.se-b.se*c.fi; } double build(int from,int to,int v,vec<int> &c){ c.push_back(to); c.push_back(from); int di=from<to?1:-1; for (int i = from+1; i != to+di; i+=di){ if(i==v)continue; while(c.back()!=from && cp(c[c.size()-2],c.back(),c.back(),i)<=0)c.pop_back(); c.push_back(i); } if(c.size()==3)return 0; double ret=0; for (int i = 2; i < c.size()-1; i++){ ret+=cp(c[1],c[i],c[1],c[i+1])/2; } return ret; } vec<int> up,down,t1,t2; void solve(){ sort(a.begin(),a.end()); double s=build(0,a.size()-1,-1,up)+build(a.size()-1,0,-1,down); double s1=build(0,a.size()-2,-1,t1)+build(a.size()-2,0,-1,t2); t1.clear();t2.clear(); s1=min(s1,build(1,a.size()-1,-1,t1)+build(a.size()-1,1,-1,t2)); for(int i=2;i<up.size()-1;i++){ t1.clear(); s1=min(s1,s+build(up[i-1],up[i+1],up[i],t1)-cp(up[i-1],up[i],up[i-1],up[i+1])/2); } for (int i = 2; i < down.size()-1; i++){ t1.clear(); s1=min(s1,s+build(down[i-1],down[i+1],down[i],t1)-cp(down[i-1],down[i],down[i-1],down[i+1])/2); } printf("%.2f\n",s1); } int main(){ while(scanf("%d",&n),n){ up.clear();down=t1=t2=up;a.clear(); for (int i = 0; i < n; i++){ int x,y; scanf("%d %d",&x,&y); a.push_back({x,y}); } solve(); } return 0; }
相关文章推荐
- POJ 3246 Game(凸包)
- poj 2187 Beauty Contest 题解(凸包模板+旋转卡壳)
- 7_6_P题 Wall 题解[poj 1113] (凸包)
- poj 3608 Bridge Across Islands题解(凸包+求两凸包间的最近点对)
- The Rotation Game (POJ 2286) 题解
- poj 3246 Game
- 【poj 2286】The Rotation Game 题意&题解&代码(C++)
- POJ 3246 Game 已翻译
- poj 1113 Wall凸包
- POJ:Flip Game
- POJ 2349 Arctic Network 最小生成树题解
- Scrambled Polygon - POJ 2007(求凸包)
- [ACM] poj 2484 A Funny Game(对称博弈)
- POJ 1753: Flip Game
- poj 1113 凸包问题
- POJ Flip Game(BFS + 位运算)
- POJ 1753 - Flip Game
- POJ 1912 A highway and the seven dwarfs(O(log N)求直线与凸包是否相交)
- poj 1753-Flip Game
- POJ 1584 A Round Peg in a Ground Hole(是否凸包 && 圆是否在凸包内)