关闭

凸包(判多边形的凹凸性)

216人阅读 评论(0) 收藏 举报
分类:

题目:ZOJ-3537

题目大意:

给定n个点的坐标,先问这些点是否能组成一个凸包,如果是凸包,问用不相交的线来切这个凸包使得凸包只由三角形组成,根据 cost(i, j) = |xi + xj| * |yi + yj| % p 算切线的费用,问最少的切割费用。

思路:先判断多边形是否是凸包,,,

凸包:和凸多边形差不多的意思,,

如何判断凸多边形:http://blog.csdn.net/kavu1/article/details/50772428

这里讲一下最简单的方法:

利用以当前顶点为中心的矢量叉乘或者计算三角形的有符号面积判断多边形的方向以及当前顶点的凹凸性。

假设当前连续的三个顶点分别是P1,P2,P3。计算向量(P1,P2),(P1,P3)的叉乘,也就是计算三角形P1P2P3的面积,得到的结果如果大于0,则表示P2点在线段P1和P3的右侧,多边形的顶点是逆时针序列。然后依次计算下一个前后所组成向量的叉乘,如果在计算时,出现负值,则此多边形时凹多边形,如果所有顶点计算完毕,其结果都是大于0,则多边形时凸多边形。

代码:

struct point
{
    int x,y;
    friend bool operator < (const point &a,const point &b)
    {
        if (a.y == b.y) return a.x < b.x;
        return a.y < b.y;
    }
} src[MAXN];
int cost[MAXN][MAXN];
int N,P;
int dp[MAXN][MAXN];

point save[MAXN],tmp[MAXN];
int cross(point p0,point p1,point p2)
{
    //cout<<"p0="<<p0.x<<"  "<<p0.y<<"  p1="<<p1.x<<"  "<<p1.y<<"   p2="<<p2.x<<"  "<<p2.y<<endl;
    return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}

int graphm(point * p,int n)//0-n-1的n个点,放在结构体里面,排序后按照逆序判断各点的凹凸性
{
    sort(p,p + n);
    save[0] = p[0];
    save[1] = p[1];
    int top = 1;
    for(int i = 0 ; i < n ; i++)
    {
        while(top && cross(save[top],p[i],save[top-1]) >= 0)
        {
            //cout<<"top="<<top<<"  i="<<i<<"  top-1="<<top-1<<endl;
            top--;
        }
        save[++top] = p[i];
    }

    int mid = top;
    for(int i = n - 2 ; i >= 0 ; i--)
    {
        while(top > mid && cross(save[top],p[i],save[top-1]) >= 0)
        {
            //cout<<"top="<<top<<"  i="<<i<<"  top-1="<<top-1<<endl;
            top--;
        }
        save[++top]=p[i];
    }
    return top;
}

求出凸包后,再求出各个相切的费用,接着就是区间DP求最小花费了,dp[i][j]为以i为起点,j为终点的凸包被切割成一个个小三角形所需要的费用

完整代代码:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <set>

using namespace std;
typedef long long ll;

const int MAXN = 310;
struct point
{
    int x,y;
    friend bool operator < (const point &a,const point &b)
    {
        if (a.y == b.y) return a.x < b.x;
        return a.y < b.y;
    }
} src[MAXN];
int cost[MAXN][MAXN];
int N,P;
int dp[MAXN][MAXN];

point save[MAXN],tmp[MAXN];
int cross(point p0,point p1,point p2)
{
    //cout<<"p0="<<p0.x<<"  "<<p0.y<<"  p1="<<p1.x<<"  "<<p1.y<<"   p2="<<p2.x<<"  "<<p2.y<<endl;
    return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}

int graphm(point * p,int n)
{
    sort(p,p + n);
    save[0] = p[0];
    save[1] = p[1];
    int top = 1;
    for(int i = 0 ; i < n ; i++)
    {
        while(top && cross(save[top],p[i],save[top-1]) >= 0)
        {
            //cout<<"top="<<top<<"  i="<<i<<"  top-1="<<top-1<<endl;
            top--;
        }
        save[++top] = p[i];
    }

    int mid = top;
    for(int i = n - 2 ; i >= 0 ; i--)
    {
        while(top > mid && cross(save[top],p[i],save[top-1]) >= 0)
        {
            //cout<<"top="<<top<<"  i="<<i<<"  top-1="<<top-1<<endl;
            top--;
        }
        save[++top]=p[i];
    }
    return top;
}

int getcost(point a,point b)
{
    return (abs(a.x + b.x) * abs(a.y+b.y)) % P;
}

int main()
{
    while (scanf("%d%d",&N,&P) != EOF)
    {
        for (int i = 0 ; i < N ; i++) scanf("%d%d",&src[i].x,&src[i].y);
        int num = graphm(src,N);
        if (num < N)
        {
            printf("I can't cut.\n");
        }
        else
        {
            memset(cost,0,sizeof(cost));
            for (int i = 0 ; i < N ; i++)
            {
                for (int j = i + 2 ; j < N ; j++) cost[i][j] = cost[j][i] = getcost(save[i],save[j]);
            }
            memset(dp,0x3f,sizeof(dp));
            for (int i = 0 ; i < N ; i++) dp[i][(i + 1) % N] = 0;//相邻两点费用为0
            for(int i=N-3;i>=0;i--)//从倒数第二个点开始枚举
            {
                for(int j=i+2;j<N;j++)
                {
                    for(int k=i+1;k<j;k++)
                    {
                        dp[i][j] = min(dp[i][j],dp[i][k] + dp[k][j] + cost[i][k] + cost[k][j]);
                    }
                }
            }
            printf("%d\n",dp[0][N - 1]);
        }
    }
    return 0;
}
0
0
查看评论

判断多边形凹凸性

1)角度法: 判断每个顶点所对应的内角是否小于180度,如果小于180度,则是凸的,如果大于180度,则是凹多边形。 2)凸包法: 这种方法首先计算这个多边形的凸包,关于凸包的定义在此不再赘述,首先可以肯定的是凸包肯定是一个凸多边形。如果计算出来的凸多边形和原始多边形的点数一样多,...
  • kavu1
  • kavu1
  • 2016-03-01 14:42
  • 3126

判断平面多边形的凹凸性

对于平面多边形的三角化处理也是计算机图形学里面的一个领域,最近由于项目的需要,需要对平面多边形进行剖分,特此对其作了些研究。 在对平面多边形进行处理的时候,很多时候需要知道多边形的凹凸性,本文介绍两种方法来进行平面多边形凹凸性的判定,文章后面会给出示例代码。 1、使用角度和判断凹凸性 我们知道...
  • swety_gxy
  • swety_gxy
  • 2017-04-14 23:51
  • 2355

opencv学习之寻找凸包,使用多边形包围轮廓

#include"stdafx.h" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include using namespa...
  • OliverkingLi
  • OliverkingLi
  • 2017-01-30 20:59
  • 1482

最小包围多边形(凸包;最小包围点集)——C代码例子

本文来自:http://alienryderflex.com/smallest_enclosing_polygon/ 这个C代码例子需要一群2维点集,如下图所示: 要获得包含这些点的最小多边形如下图所示: 查找点集最小多边形的一种方法是——将所有点都传到函数中计算。 ...
  • hjh2005
  • hjh2005
  • 2013-07-05 09:05
  • 5357

解凸包问题5种算法

转载原文:http://blog.csdn.net/bone_ace/article/details/46239187 前言: 首先,什么是凸包?  定义:对于平面上的一个点集合(有限或无限),如果以集合中任意两点P和Q为端点的线段都属于该集合,我们说这个集合是凸的!可以直接说任意两点直...
  • Touch_Dream
  • Touch_Dream
  • 2016-10-05 16:40
  • 1970

判断点在任意多边形(包括凹凸边形)内

原文链接:点击打开链接 题目地址:http://www.cnblogs.com/try86/archive/2012/04/22/2465416.html 这一题,若点在边上,也将点看做成多边形内。 对于凸多边形有很多种方法判断点在多边形内,但若是凹多边形,则靠谱的方法不多,可以谷歌一...
  • PSU_VJD
  • PSU_VJD
  • 2015-12-26 14:44
  • 543

平面点集的凸包

概念:给定一个平面的点集q,求覆盖所有点的最小凸多边形(在多边形边上,或内部)。 主要求解思想: 采用分治算法 如图,先找出y坐标最大和做小的点,并入此多边形的顶点集(因为是y坐标最大和最小,所以此直线左边和右边的凸包合起来还是凸包); 对直线左右的点进行递归处理: 如直线左边,...
  • u013337743
  • u013337743
  • 2015-07-08 20:40
  • 1757

算法:分治法求凸包上的点以及由凸包所构成的多边形的面积

在平面上有若干个点,编写程序求其凸包上的点以及由凸包所构成的多边形的面积。 输入要求:输入的第一行是一个整数n,表示点的个数。其后的n行,每行有两个整数,中间空格隔开,分别表示点的X,Y坐标。 输出要求:输出的第1行为一个整数m,表示凸包上点的个数,其后的m行每行有两个整数,分别表示凸包上点的坐...
  • Eric_KEY
  • Eric_KEY
  • 2016-11-13 17:44
  • 892

计算几何之求取三维维点集的凸包/ 凸多边形包围盒(2D、3D点集)

QuickHull(二维、三维空间点专用) // 方法思路:寻找一个凸核,并慢慢扩张成一个凸体包围盒; 1. 寻找各个方向上极值点 (2D则是4个,3D则是6个) 构成凸核(注意这个凸核一定包含于最终的凸包); 2. 删除凸核内的点集; 3. 若剩余点集非空,寻找各边(3D是各面) 的最远点加入凸包...
  • z444_579
  • z444_579
  • 2016-10-23 17:59
  • 776

基于c#的两种最小凸包的生成(三硬币法与串行算法)

凸包(Convex Hull)是一个计算几何(图形学)中的概念。 在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。 X的凸包可以用X内所有点(X1,...Xn)的线性组合来构造.
  • u011609113
  • u011609113
  • 2014-10-03 14:22
  • 1230
    个人资料
    • 访问:13892次
    • 积分:884
    • 等级:
    • 排名:千里之外
    • 原创:76篇
    • 转载:2篇
    • 译文:0篇
    • 评论:3条