凸包(判多边形的凹凸性)
来源:互联网 发布:linux文件权限 编辑:程序博客网 时间:2024/04/30 07:10
题目: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
- 凸包(判多边形的凹凸性)
- 判断平面多边形的凹凸性
- 凹凸多边形的拆分
- 判断多边形凹凸性
- 判断多边形凹凸性
- 向量叉积的应用(三角形面积,线段相交,多边形面积,多边形凹凸性)
- Open gl判断任意多边形的凹凸性
- hdoj2108Shape of HDU【凹凸多边形的判定】
- hdu 2108 判断多边形的凹凸
- 判断多边形凹凸(计算几何基础)
- 判断多边形凹凸(计算几何)
- 判断多边形凹凸
- 二维向量的叉乘判断凹凸多边形
- hdu2036 计算坐标内任意多边形的面积 含凹凸
- Shape of HDU 几何问题判断多边形凹凸性
- HDOJ 2108 Shape of HDU (判断凹凸多边形)
- 判断闭合曲线的凹凸性(比如判断四边形的凹凸情况)
- 求多边形或轮廓的凸包(Hull)
- Gym 101158C Distribution Center(思路题)
- 分布式环境下限流方案的实现redis RateLimiter Guava,Token Bucket, Leaky Bucket
- 深入理解Java多态机制
- Android内存优化
- MySQL InnoDB存储结构
- 凸包(判多边形的凹凸性)
- 【知了堂学习笔记】Java中static关键字的一些简单使用方法
- Java操作Json
- iOS 后台返回json解析出现的null的解决办法
- Android轻量级框架XSnow
- shell基础:脚本执行方式
- 夜灵的Html笔记Day04——CSS3basic
- Java设计模式之代理模式
- POJ 3667 Hotel & HDU 2871 Memory Control 线段树区间合并