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

原创 2017年08月31日 19:29:14

题目: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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

判断多边形凹凸性

1)角度法: 判断每个顶点所对应的内角是否小于180度,如果小于180度,则是凸的,如果大于180度,则是凹多边形。 2)凸包法: 这种方法首先计算这个多边形的凸包,关于凸包的定义在...
  • kavu1
  • kavu1
  • 2016-03-01 14:42
  • 1919

判断平面多边形的凹凸性

两种方法来进行平面多边形凹凸性的判定

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

向量叉积的应用(三角形面积,线段相交,多边形面积,多边形凹凸性)

向量叉积有甚多应用,包括求三角形面积,判断线段相交,求多边形面积,判断多边形凹凸性,而且不需要推大量公式,误差较小,非常实用,下面是代码 //向量叉积的应用 #include #defin...

PCL—低层次视觉—点云分割(基于凹凸性)

转自:http://www.cnblogs.com/ironstark/p/5027269.html PCL—低层次视觉—点云分割(基于凹凸性) 1.图像分割的两条思路 ...

关于min max 函数凹凸性,以及期望库存,期望缺货量的性质

有两个性质比较重要,经常用到:

OpenCV轮廓、多边形逼近、关键点、周长和面积、边界框、矩、轮廓树、凹凸包、几何直方图、匹配

OpenCv轮廓高级应用(轮廓匹配,几何直方图)     最近再次用到了opencv轮廓,在这里结合作者冰山一角的博客(http://www.cnblogs.com/slysky/)以及自己的体会在...

poj3348Cows(凸包求多边形面积)

题目链接: http://poj.org/problem?id=3348 思路: 先对点进行排序,然后求出凸包。对凸包上的点进行面积计算,即将多边形面积分成多个三角形,利用叉积计算即可。 ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)