整理的算法模板合集: ACM模板


目录

  • 最优三角剖分
  • UVA1331 最大面积最小的三角剖分 Minimax Triangulation

最优三角剖分

问题描述:

给一个有n个顶点的凸多边形,有很多方法进行三角剖分(polygon triangulation) 。给每个三角形规定一个权函数w(i,j,k)w(i,j,k)w(i,j,k)(比如三角形的周长或者三顶点的权和或者三角形的面积等等),求让所有三角形权和最大的方案。


 这个问题的关键在于状态的定义,因为如果允许随意切割,显然任意“半成品” 多边形的各个顶点可以是原多边形中随意选取的,很难简洁的定义成状态。但我们又可以发现,对于同一种切割方法,我们可以有多种切割顺序,但切割方法就已经决定了这个方法产生的结果,我们只要计算其中一种切割顺序就好了,所以不如把决策顺序规范化。

定义 d[i,j] 为从顶点 i 开始到顶点 j所构成的多边形的最大三角剖分权和(编号是逆时针分配的),则边i→j 在此多边形内一定恰好属于一个三角形 i→j→k ,所以多边形就被分成了三部分:三角形ikj 及其左右两部分的小多边形。这个切割方法保证了两个子多边形它们的顶点编号是连续的。所以我们只需要每次将代表这个多边形的两个顶点(始、末)作为分割后的其中一个三角形的一条边,然后枚举第三个顶点 k 的情况,再依次分割下去直到分割完成。

状态转移方程:d[i,j]=max{d[i,k]+d[k,j]+w(i,j,k)}d[i,j] = max\{d[i,k]+d[k,j]+w(i,j,k)\}d[i,j]=max{d[i,k]+d[k,j]+w(i,j,k)}
时间复杂度:O(n3)O(n^3)O(n3)
最终的答案:d[1][n−1]d[1][n - 1]d[1][n−1]

下面给出例题:

UVA1331 最大面积最小的三角剖分 Minimax Triangulation

本题要求的是最大面积最小的三角剖分,所以转移方程有所变化。

需要注意的是,本题并没有指明这个多边形的凹凸性,所以对于凹多边形的情况,需要加上一个判断,即判断Δijk是否是合法的三角形:如果Δijk内部含有多边形的一个顶点,那么就是不合法的三角形。

注意本题还会卡精度,所以需要判断精度误差

要注意我们这里使用的判断三角形是否合法使用的是O(n)O(n)O(n)的做法(枚举点 i(i≠a,i≠b,i≠c)i(i\neq a, i\neq b, i\neq c)i(i​=a,i​=b,i​=c),若△a,b,i+S△a,c,i+S△b,c,i=S△a,b,c\triangle_{a,b,i}+S\triangle_{a,c,i}+S\triangle_{b,c,i} = S\triangle_{a,b,c}△a,b,i​+S△a,c,i​+S△b,c,i​=S△a,b,c​,则点 i 位于 △a,b,c\triangle_{a,b,c}△a,b,c​​内部,则三角形 a,b,c 是不合法的。),使得总体的时间复杂度达到了O(n4)O(n^4)O(n4)。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>using namespace std;
typedef long long ll;
const int N = 507, M = 5000007, INF = 0x3f3f3f3f;
const double eps = 1e-6;struct Point{double x, y;
}a[N];double f[N][N];int n;double Area(double a, double b, double c)
{double p = (a + b + c) / 2.0;return sqrt(p * (p - a) * (p - b) * (p - c));
}double get_dist(Point a, Point b)
{return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}bool check(int A, int B, int C)//判断凹多边形中切出来的是不是合法的三角形
{for(int i = 1; i <= n; ++ i){if(i != A && i != B && i != C){double s = Area(get_dist(a[A], a[B]), get_dist(a[B], a[C]), get_dist(a[A], a[C]));double p = Area(get_dist(a[A], a[B]), get_dist(a[B], a[i]), get_dist(a[A], a[i])) + Area(get_dist(a[A], a[i]), get_dist(a[i], a[C]), get_dist(a[A], a[C])) + Area(get_dist(a[i], a[B]), get_dist(a[B], a[C]), get_dist(a[i], a[C]));if(fabs(s - p) < eps)return false;}}return true;
}int main()
{int t;scanf("%d", &t);while(t -- ){scanf("%d", &n);for(int i = 1; i <= n; ++ i){scanf("%lf%lf", &a[i].x, &a[i].y);}for(int i = 1; i <= n - 2; ++ i){f[i][i + 2] = Area(get_dist(a[i], a[i + 1]), get_dist(a[i + 1], a[i + 2]), get_dist(a[i + 2], a[i]));}for(int len = 3; len < n; ++ len){//至少长度为3 至少三个点for(int i = 1; i <= n - len; ++ i){int j = i + len;f[i][j] = INF;for(int k = i + 1; k < j; ++ k){if(check(i, j, k)){//题目要求的是最大三角形最小,所以找到最大三角形转移f[i][j] = min(f[i][j], max(max(f[i][k], f[k][j]), Area(get_dist(a[i], a[k]), get_dist(a[k], a[j]), get_dist(a[j], a[i]))));}}}}printf("%.1f\n", f[1][n]);}
}

另一种方法是根据三角形三个点的两个向量的叉积是否小于0,如果小于0说明不合法,有点玄学,我代码也没调出来,就放一个那位想出来这个思路的大佬的代码吧。如果可以O(1)O(1)O(1)判断的话整体的时间复杂度就降到了O(n3)O(n^3)O(n3),虽然数据只有 50…
大佬博客的链接:https://www.luogu.com.cn/blog/user17952/solution-uva1331

#include <iostream>
#include <cstdio>
#include <algorithm>using namespace std;const int Maxn = 0x3f3f3f3f;
const int N = 55;
int nxt[N], f[N][N], n, m, Ans;struct point
{int x, y;point() {}point(int X, int Y):x(X), y(Y) {}friend inline point operator - (const point &a, const point &b) {return point(b.x - a.x, b.y - a.y); }friend inline int operator * (const point &a, const point &b){return a.x * b.y - b.x * a.y;}
}a[N];inline int Max(int x, int y) {return x > y ? x : y;}
inline int Min(int x, int y) {return x < y ? x : y;}
inline void CkMin(int &x, int y) {if (x > y) x = y;}inline int dp(int l, int r)
{if (f[l][r] != -1) return f[l][r];if (r == nxt[l]) return f[l][r] = 0;int res = Maxn;for (int i = nxt[l]; i != r; i = nxt[i]){int tmp = (a[i] - a[r]) * (a[i] - a[l]);if (tmp > 0) CkMin(res, Max(Max(dp(l, i), tmp), dp(i, r)));}return f[l][r] = res;
}int main()
{while (scanf("%d", &m) != EOF) {while (m--) { scanf("%d", &n);for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].x, &a[i].y);for (int i = 1; i < n; ++i)nxt[i] = i + 1; nxt[n] = 1;int sum = 0; for (int i = 1; i < n; ++i)sum += a[i] * a[i + 1]; sum += a[n] * a[1];if (sum < 0)for (int i = 1, im = n >> 1; i <= im; ++i) swap(a[i], a[n - i + 1]);for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)f[i][j] = -1;for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)    if (i != j) dp(i, j);Ans = Maxn;for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)if (i != j) CkMin(Ans, Max(f[i][j], f[j][i]));printf("%.1lf\n", (double)Ans / 2.0);}}return 0;
}

【动态规划、计算几何】最优三角剖分相关推荐

  1. 动态规划--凸多边形最优三角剖分

    算法设计与实现  王晓东 题目描述: 用多边形顶点的逆时针序列表示凸多边形,即P={v0,v1,-,vn-1}表示具有n条边的凸多边形. 给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函 ...

  2. 动态规划---例题5.凸多边形最优三角剖分问题

    一.题目描述 通常,用多边形顶点的序列来表示一个凸多边形,即P=<v0 ,v1 ,- ,vn-1>表示具有n条边v0v1,v1v2,- ,vn-1vn的一个凸多边形,其中,约定v0 = v ...

  3. —【动态规划】凸多边形最优三角剖分

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 0014 ...

  4. 最优java三角剖分算法代码,动态规划之凸多边形的最优三角剖分

    该题的题意大致为:一个n个角的凸多边形,,用互不相交的弦将其分为一个个的三角形,每个三角形的权值都是由三角形的边和弦组成权值函数w,求解如何划分才能使所有的角上的权值和达到最小. 根据动态规划算法的主 ...

  5. 7-3 凸多边形最优三角剖分 (10 分)(思路+详解+分析题意+动态规划)Come Baby!!!!!!!!!

    一:题目: 给定n边凸多边形P,要求确定该凸多边形的三角剖分(将多边形分割成n-2个三角形),使得该三角剖分中诸三角形上权之和为最小.各边弦的权值以由输入数据给出,以无向图的形式表示.三角形的权值等于 ...

  6. DP——最优矩阵链乘最优三角剖分

    最优矩阵链乘: 一个n*m的矩阵乘一个m*p的矩阵等于一个n*p的矩阵,运算量为mnp,现在有一组n个矩阵组成的序列,求运算量的最小值. 这是DP中的最优矩阵链乘问题,我们可以这么理解:用一个d[i] ...

  7. 动态规划最优二叉搜索树C语言,【算法导论】动态规划之“最优二叉搜索树”...

    详解动态规划之"最优二叉搜索树" 之前两篇分别讲了动态规划的"钢管切割"和"矩阵链乘法",感觉到了这一篇,也可以算是收官之作了.其实根据前两 ...

  8. 第十五章 动态规划(最优二叉搜索树)

    第15章动态规划(最优二叉搜索树) 15.5 最优二叉搜索树 15.5 练习 15.5-1 15.5-2 15.5-3 15.5-4 说在前面的话: 为什么单独拿出来发? 1.由于排版篇幅问题,放一起 ...

  9. 凸多边形最优三角剖分

    凸多边形最优三角剖分 问题描述 (1)凸多边形的三角剖分:将凸多边形分割成互不相交的三角形的弦的集合T. (2)最优剖分:给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函数w.要求确定该 ...

最新文章

  1. vue之父子组件通信
  2. c++ 中this 和 *this区别
  3. 大数据处理时的一种BitMap小算法
  4. CBO Cost Formulas基于成本优化器的成本计算公式大全
  5. python import random 报错_Python import random报错处理办法
  6. 【交互】【随机】Lost Root(CF1061F)
  7. java英文拼写检查并自动纠正
  8. LeetCode——350. 两个数组的交集 II
  9. 软件的可扩展性与框架的可交互性
  10. mybatis源码环境搭建
  11. python解释器遇到if __name__==__main__会如何做?
  12. Oracle 11g for Windows 简体中文版的安装过程
  13. 11 个非常受欢迎的 JavaScript 动画库
  14. js方法点击复制文本
  15. ios 基础知识点总结
  16. mongodb分组查询 php,MongoVUE下实现MongoDB的Group分组查询
  17. 360云服务器合作,360云主机速度(云服务器)
  18. linux 光纤网卡 软路由,联想M720Q、光网卡、Pon stick、Openwrt我的完美软路由折腾记...
  19. r语言 支持向量机实现_支持向量机解密:R中的实现
  20. ping 命令的用法大全(图文详解)

热门文章

  1. 如何使用OpenCV自动校正文本图像
  2. Im2Mesh GAN:从一张RGB图像中恢复3D手部网格
  3. 不用3D建模软件,如何用数学公式创造一个女孩?会眨眼,有光影的那种
  4. mysql存储、function、触发器等实例
  5. P1515 旅行(简单搜索)
  6. 你应该知道的高性能无锁队列Disruptor
  7. 第六十二课、单例类模板
  8. ARM Linux 3.x的设备树(Device Tree)【转】
  9. wp配置后台自动更新
  10. RAID0、RAID1、RAID0+1模式实战评测