http://poj.org/problem?id=2079 (题目链接)

题意

  求凸包内最大三角形面积

Solution

  旋转卡壳。

  只会n²的做法,但是竟然过了。就是枚举每一个点,然后旋转卡壳另外两个点。先固定i,j这2个邻接的顶点。然后找出使三角形面积最大的那个k点。然后再固定i,枚举j点,由于k点是随着j点的变化在变化,所以k点不必从开头重新枚举。

  之后去网上看了下O(n)的做法,当时就感觉有点鬼,打了一遍交上去Wa了,鬼使神差拍出一组数据好像可以把网上O(n)的做法全部卡掉,但是我也还搞不清为什么这样做是错的。

数据: 

-7 0 
-5 1 
-1 5 
-2 8 

0 7 
1 5 
5 1 
8 2 
4 8 

0 -7 
4 -8 
8 -2 
5 -1 
1 -5 
-1

  这3个数据都是同一个凸包,面积都是15.00。  

O(n)代码

// poj2079
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#define esp 1e-8
#define inf 2147483640
#define LL long long
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {
LL x=0,f=1;char ch=getchar();
while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int maxn=50010;
struct point {int x,y;}p[maxn],p0; int cross(point p0,point p1,point p2) {
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double dis(point a,point b) {
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b) {
int t=cross(p0,a,b);
if (t>0) return 1;
if (t<0) return 0;
return dis(p0,a)<dis(p0,b);
}
int Graham(int n) {
if (n==1) return 1;
int k=1,top=2;
for (int i=1;i<=n;i++)
if (p[i].y==p[k].y ? p[i].x<p[k].x : p[i].y<p[k].y) k=i;
p0=p[k];p[k]=p[1];p[1]=p0;
sort(p+2,p+1+n,cmp);
for (int i=3;i<=n;i++) {
while (top>1 && cross(p[top-1],p[top],p[i])<=0) top--;
p[++top]=p[i];
}
return top;
}
double RC(int n) {
int ans=0;
p[n+1]=p[1];
int i=1,j=2,k=3,t;
while (k!=1) {
int ii=i,jj=j,kk=k;
while ((t=abs(cross(p[i],p[k],p[j])))<abs(cross(p[i],p[k+1],p[j]))) k=k%n+1;
ans=max(ans,t);
while ((t=abs(cross(p[i],p[k],p[j])))<abs(cross(p[i],p[k],p[j+1]))) j=j%n+1;
ans=max(ans,t);
while ((t=abs(cross(p[i],p[k],p[j])))<abs(cross(p[i+1],p[k],p[j]))) i=i%n+1;
ans=max(ans,t);
if (ii==i && jj==j && kk==k) k=k%n+1;
}
return (double)ans/2.0;
}
int main() {
int n;
while (scanf("%d",&n)!=EOF && n>0) {
for (int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y);
n=Graham(n);
printf("%.2f\n",RC(n));
}
return 0;
}

O(n²)代码

// poj2079
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#define esp 1e-8
#define inf 2147483640
#define LL long long
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {
LL x=0,f=1;char ch=getchar();
while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int maxn=50010;
struct point {int x,y;}p[maxn],p0; int cross(point p0,point p1,point p2) {
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double dis(point a,point b) {
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b) {
int t=cross(p0,a,b);
if (t>0) return 1;
if (t<0) return 0;
return dis(p0,a)<dis(p0,b);
}
int Graham(int n) {
if (n==1) return 1;
int k=1,top=2;
for (int i=1;i<=n;i++)
if (p[i].y==p[k].y ? p[i].x<p[k].x : p[i].y<p[k].y) k=i;
p0=p[k];p[k]=p[1];p[1]=p0;
sort(p+2,p+1+n,cmp);
for (int i=3;i<=n;i++) {
while (top>1 && cross(p[top-1],p[top],p[i])<=0) top--;
p[++top]=p[i];
}
return top;
}
double RC(int n) {
int ans=0;
p[n+1]=p[1];
for (int i=1;i<=n;i++) {
int j=i%n+1,k=(i+1)%n+1;
while (abs(cross(p[i],p[j],p[k]))<abs(cross(p[i],p[j],p[k+1]))) k=k%n+1;
while (i!=j && i!=k) {
ans=max(ans,abs(cross(p[i],p[j],p[k])));
while (abs(cross(p[i],p[j],p[k]))<abs(cross(p[i],p[j],p[k+1]))) k=k%n+1;
j=j%n+1;
}
}
return (double)ans/2.0;
}
int main() {
int n;
while (scanf("%d",&n)!=EOF && n>0) {
for (int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y);
n=Graham(n);
printf("%.2f\n",RC(n));
}
return 0;
}

  

【poj2079】 Triangle的更多相关文章

  1. 【LeetCode】Triangle 解决报告

    [称号] Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjac ...

  2. 【leetcode】Triangle (#120)

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  3. 【leetcode】triangle(easy)

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  4. 【Leetcode】Triangle

    给定一个由数字组成的三角形,从顶至底找出路径最小和. Given a triangle, find the minimum path sum from top to bottom. Each step ...

  5. 【数组】Triangle

    题目: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjace ...

  6. 【Leetcode】【Medium】Triangle

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  7. 【poj1085】 Triangle War

    http://poj.org/problem?id=1085 (题目链接) 题意 A,B两人玩游戏,在一个大三角形上放火柴,若A放上一根火柴后成功组成一个三角形,那么这个三角形就归属于A,并且A被奖励 ...

  8. 【计数】【UVA11401】 Triangle Counting

    传送门 Description 把1……n这n个数中任取3个数,求能组成一个三角形的方案个数 Input 多组数据,对于每组数据,包括: 一行一个数i,代表前i个数. 输入结束标识为i<3. O ...

  9. 【HDOJ6300】Triangle Partition(极角排序)

    题意:给定3n个点,保证没有三点共线,要求找到一组点的分组方案使得它们组成的三角形之间互不相交. n<=1e3 思路:以y为第一关键字,x为第二关键字,按x递减,y递增排序 #include&l ...

随机推荐

  1. JavaScript 中的原型声明和用法总结

    下面是自己写的一个关于js的拖拽的原型声明:代码如下 需要注意的问题包括: 1.this的指向到底是指向谁--弄清楚所指的对象 2.call()方法的使用 3.直接将父级原型赋给子级与使用for将其赋 ...

  2. 迷你DVD管理器项目

    package chapter5; import java.util.*; public class MiniDVD { public static void main(String[] args){ ...

  3. 介绍linux下利用编译bash设置root账号共用的权限审计设置

    在日常运维工作中,公司不同人员(一般是运维人员)共用root账号登录linux服务器进行维护管理,在不健全的账户权限审计制度下,一旦出现问题,就很难找出源头,甚是麻烦!在此,介绍下利用编译bash使不 ...

  4. Gradle的HelloWorld

    Gradle的脚本名为  build.gradle task hello{ doLast{ println("Hello World") } } 运行:gradle -q hell ...

  5. 17Mybatis_动态sql-sql片段

    这篇文章讲一下sql片段. 讲一下sql片段的的需求: 将上边实现的动态sql判断代码块抽取出来,组成一个sql片段.其它的statement中就可以引用sql片段. 方便程序员进行开发. 第一步我们 ...

  6. 第一章 初识MVC4

    1.MVC模式 Mvc将应用程序分离为三个部分: Model:是一组类,用来描述被处理的数据,同时也定义这些数据如何被变更和操作的业务规则.与数据访问层非常类似. View:是一种动态生成HTML的模 ...

  7. PyQT制作视频播放器

    Python应用03 使用PyQT制作视频播放器   作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载. 最近研究了Python的两个GUI包,Tki ...

  8. C#把某个数组的一部分复制到另一个数组中的两种方法:Buffer.BlockCopy和Array.Copy

    static void Main(string[] args) { , , , , , }; ;//目标数组大小 int int_size = sizeof(int);//用于获取值类型的字节大小. ...

  9. 3D数学基础:四元数与欧拉角之间的转换

    在3D图形学中,最常用的旋转表示方法便是四元数和欧拉角,比起矩阵来具有节省存储空间和方便插值的优点.本文主要归纳了两种表达方式的转换,计算公式采用3D笛卡尔坐标系: 单位四元数可视化为三维矢量加上第四 ...

  10. JS实现点击跳转登陆邮箱

    前言 注册的过程中往往需要填写邮箱,并登陆邮箱进行验证.利用JS可以实现针对不同的邮箱进行点击登录验证,以下为实现方案,很简单 代码 邮箱域名数据   1 2 3 4 5 6 7 8 9 10 11 ...