动态规划【凸多边形三角划分】
第3章动态规划法

算法设计与分析 2
问题的分解
将待求解问题分解为若干子问题,通过子问题的解得 到原问题的解,这是问题求解的有效途径。但是如何 实施分解? 分治策略的基本思想是将规模为n的问题分解为k个规 模较小的子问题,各子问题相互独立但与原问题求解 策略相同。并不是所有问题都可以这样处理。 问题分解的另一个途径是将求解过程分解为若干阶段 (级),依次求解每个阶段即得到原问题的解。通过 分解得到的各子阶段不要求相互独立,但希望它们具 有相同类型,而且前一阶段的输出可以作为下一阶段 的输入。这种策略特别适合求解具有某种最优性质的 问题。 贪心法属于这类求解策略:对问题P(n),其求解过程 中各贪心选择步骤构成决策序列D=<D1,D2,..Dk>。Di 的最优性仅依赖于D1,D2,..Di-1。贪心法不保证决策 序列D最后求出解的最优性。
算法设计与分析 8
MultiStage_Graph算法复杂度
G用邻接矩阵表示,对于S2到S5的主循环执行 n次。为求满足wjr+cr=min{wji+ci|<j,i>是G的边} 的r,最多要求n-1次比较。因此时间复杂性为 O(n2)。除输入G,输出P外,要求附加存储空 间c、D。 如果G采用邻接表表示,求满足最小性的节点r 仅对属于G的边<j,r>访问一次,此算法的时间 复杂性应该为O(n+e)(e为G的边数)。 一般地,为避免递归过程中的重复计算,每个 子问题首次处理时将结果保存以备查。在上面 的过程中,每一次求得的cj都必须记录下来。
算法设计与分析 5
一个多段图例子
阶段4: C(7,t)=w(7,t)=8 ,C(8,t)=w(8,t)=4 记 D(u,v)是G中起点为 u,终点为v的最短路径,C(u,v) 阶段 3: C(4,t)=min{w(4,7)+C(7,t), w(4,8)+C(8,t)}=12 是该路径上各边权的和。设 D(s,t)= <s,vi1,vi2…vik-1,t>,vir C(5,t)=min{w(5,7)+C(7,t), w(5,8)+C(8,t)}=10 属于Vr (r=1,2..k-1),则D(vi1 ,t)= <vi1,vi2,…vik-1,t>是从 C(6,t)=min{w(6,7)+C(7,t), w(6,8)+C(8,t)}=8 vi1出发到 t的最短路径,D(vi2,t)= <vi2,…vik-1,t>是从vi2出 阶段 2: C(1,t)=min{w(1,4)+C(4,t), w(1,5)+C(5,t)}=19 发到 t的最短路径等等。设 u属于 Vi,有: C(2,t)=min{w(2,4)+C(4,t), w(2,5)+C(5,t), w(2,6)+C(6,t)}=17 C(u,t)=min{w(u,v)+C(v,t)} (4.1) C(3,t)=min{w(3,5)+C(5,t), w(3,6)+C(6,t)}=13 v∈Vi+1 阶段1: C(s,t)=min{w(s,1)+C(1,t), w(s,2)+C(2,t), w(s,3)+C(3,t)}=16 算法设计与分析 沿求解中带下划线的项回溯,得最短路径解: D(s,t)= <s,3,5,8,t>6
《算法设计与分析》第3章 动态规划法

最优解的递推关系 定义m[i:j],表示矩阵连乘A[i:j]所需的最少计算 量 则有: i j 0 m[i ][ j ] i j minj{m[i ][ k ] m[k 1][ j ] pi 1 pk p j } i k
假设:N个矩阵的维数依序放在一维数组p中, 其中Ai的维数记为Pi-1×Pi
A=A1×A2×A3×…×An
A=(A1×A2×…×Ak) × (Ak+1×Ak+2×…×An)
B
C
1.2 穷举法
穷举法:列举出所有可能的计算次序,并计算出 每一种计算次序相应需要的数乘次数,从中找出 一种数乘次数最少的计算次序。
穷举法复杂度分析: 对于n个矩阵的连乘积,设其不同的计算次序有P(n)种。 由于每种加括号方式都可以分解为两个子连乘的加括号问题: (A1...Ak)(Ak+1…An)可以得到关于P(n)的递推式如下:
【程序】矩阵连乘的 穷举法实现 int MatrixChain::LookupChain(int i, int j) { if(i==j) return 0; int u=LookupChain(i+1,j)+p[i-1]*p[i]*p[j]; //k=i s[i][j]=i; //记录最优分解位置 for ( int k=i+1;k<j; k++ ) { //遍历k int t=LookupChain(i,k)+LookupChain(k+1,j) +p[i]*p[k+1]*p[j+1]; if (t<u) { u=t; s[i][j]=k; //记录最优分解位置 } } int MatrixChain::LookupChain() return u; { } return LookupChain(1,n);
凸多边形最优三角剖析_动态规划

凸多边形最优三⾓剖析_动态规划⼀、问题描述多边形的三⾓剖分:将多边形分割成互不相交的三⾓形的弦的集合T。
最优剖析:给定凸多边形的三⾓剖分,使得该三⾓剖分中诸三⾓形上权之和最⼩(是所有的三⾓形的权值之和,不是只计算边和弦的权值之和)。
⼆、解题思路及所选算法策略的可⾏性分析基本思路:动态规划。
最优⼦结构:若凸(n+1)边形p={V0,V1,…,VN}的最优三⾓剖分T包含三⾓形V0VkVn, 1<=k<n。
则T的权为3个部分权的和:三⾓形V0VkVn的权,⼦多边形{V0,V1,…,Vk}和{Vk,Vk+1,…,Vn}的权之和。
可断⾔,有T确定的这2个⼦多⼥性的三⾓剖析也是最优。
因为若有更⼩的三⾓剖析将导致T不是最优的三⾓剖析的⽭盾递归结构:定义t[i][j],1<=i<j<=n为凸⼦多边形{Vi-1,Vi,…,Vj}的最优三⾓剖分所对应的权函数值,即其最优值。
最优剖分包含三⾓形Vi-1VkVj的权,⼦多⼥性{Vi-1,Vi,…,Vk}和{Vk,Vk+1,…,Vj}的权之和。
凸(n+1)边形P的最优权值为t[1][n]。
T[1][n]=min{t[1][k]+t[k+1][n]+w(V0VkVn)|1<=k<n}设退化的多边形{Vi-1,Vi}具有的权值为0,因为此刻够不成多边形。
三、伪代码描述及复杂度分析伪代码:Public class triangle{初始化各点两两相连权重;初始化所有⼆顶点多边形权值为0;//循环求解t[i][j]For(⼦多边形的始末顶点间隔步长){For(起始点位置){该层循环起始点对应末点的位置;求解t[i][j];记录第三点位置;找到最⼩权值位置;}}}复杂度分析:对于n规模的问题,算法需要申请n*n空间的⼆位数组,所以空间复杂度为O(n^2)。
求解问题⽤到三层for循环,所以时间复杂度为O(n^3)。
四、代码实现package 动态规划;public class triangle {private int n;// n多边形private int[][] weight;// 边的权值数组public triangle(int n) {this.n = n;this.weight = new int[n][n];}public static void main(String[] args) {triangle triangulation = new triangle(6);initTriangulation(triangulation);int n = triangulation.getN();// 凸多边形的边数int[][] t = new int[n][n];// t[i][j]表⽰顶点{Vi-1,Vi...Vj}组成的多边形的最优三⾓形剖分的权值 int[][] s = new int[n][n];// s[i][j]表⽰与Vi-1和Vj⼀起构成三⾓形的第三个顶点的位置triangulation.minWeightTriangulation2(triangulation.getN() - 1, t, s);System.out.println(t[1][5]);}// 初始化weight数组的信息public static void initTriangulation(triangle triangulation) {int[][] weight = { { 0, 2, 2, 3, 1, 4 }, { 2, 0, 1, 5, 2, 3 }, { 2, 1, 0, 2, 1, 4 },{ 3, 5, 2, 0, 6, 2 }, { 1, 2, 1, 6, 0, 1 }, { 4, 3, 4, 2, 1, 0 } };triangulation.setWeight(weight);}// 得到最优的三⾓形剖分,n是总边数-1public void minWeightTriangulation(int n, int[][] t, int[][] s) {// 初始化所有的⼆顶点多边形权值为0for (int i = 1; i <= n; i++) {t[i][i] = 0;}// 循环求解t[i][j]for (int r = 2; r <= n; r++) {// (j-i)的范围[2,n]// 当r=2时,循环实际上是在给t赋边的值,即相邻的两个顶点的权值,例如t[1][2],t[2][3]... for (int i = 1; i <= n - r + 1; i++) {// i的范围[1,n+1-r],这⾥i要保证i+r<=nint j = i + r - 1;t[i][j] = t[i + 1][j] + getWeight(i - 1, i, j);// 这⾥实际上就是k=i// t[i][j] = t[i][i] + t[i + 1][j] + getWeight(i - 1, i, j)s[i][j] = i;// i-1,i,j// 循环k,范围是[i+1,j-1],求出最⼩的t[i][j]for (int k = i + 1; k < j; k++) {// k是i和j之间的中间顶点int u = t[i][k] + t[k + 1][j] + getWeight(i - 1, k, j);// 以k作为划分得到的权值if (u < t[i][j]) {// 如果权值更⼩,那么同时更新t[i][j]和s[i][j]t[i][j] = u;s[i][j] = k;}}}}}// 我的写法,在第⼆个循环这⾥不同,没有什么差别,只是我易于我理解public void minWeightTriangulation2(int n, int[][] t, int[][] s) {// 初始化所有的⼆顶点多边形权值为0for (int i = 1; i <= n; i++) {t[i][i] = 0;}// 循环求解t[i][j]for (int r = 1; r <= n; r++) {// r=(j-i)的范围[1,n]// 当r=1时,循环实际上是在给t赋边的值,即相邻的两个顶点的权值,例如t[1][2],t[2][3],t[3][4]... for (int i = 1; i <= n - r; i++) {// i的范围[1,n-r],这⾥i要保证 j=i+r<=nint j = i + r;t[i][j] = t[i + 1][j] + getWeight(i - 1, i, j);// 这⾥实际上就是k=i// t[i][j] = t[i][i] + t[i + 1][j] + getWeight(i - 1, i, j)s[i][j] = i;// i-1,i,j// 循环k,范围是[i+1,j-1],求出最⼩的t[i][j]for (int k = i + 1; k < j; k++) {// k是i和j之间的中间顶点int u = t[i][k] + t[k + 1][j] + getWeight(i - 1, k, j);// 以k作为划分得到的权值if (u < t[i][j]) {// 如果权值更⼩,那么同时更新t[i][j]和s[i][j]t[i][j] = u;s[i][j] = k;}}}}}// 计算⼀个三⾓形的权值之和public int getWeight(int i, int j, int k) {return weight[i][j] + weight[j][k] + weight[i][k];}public int getN() {return n;}public void setN(int n) {this.n = n;}public int[][] getWeight() {return weight;}public void setWeight(int[][] weight) {this.weight = weight;}}五、代码运⾏结果截图。
4种常见的动态规划模型

例谈四种常见的动态规划模型动态规划是解决多阶段决策最优化问题的一种思想方法,本文主要结合一些例题,把一些常见的动态规划模型,进行归纳总结。
(一)、背包模型可用动态规划解决的背包问题,主要有01背包和完全背包。
对于背包的类型,这边就做个简单的描述:n个物品要放到一个背包里,背包有个总容量m,每个物品都有一个体积w[i]和价值v[i],问如何装这些物品,使得背包里放的物品价值最大。
这类型的题目,状态表示为:f[j]表示背包容量不超过j时能够装的最大价值,则状态转移方程为:f[j]:=max{f[j-w[i]]+v[i]},边界:f[0]:=0;简单的程序框架为:beginreadln(m,n);for i:=1to n do readln(w[i],v[i]);f[0]:=0;for i:=1to m dofor j:=1to n dobeginif i>=w[j]then t:=f[i-w[j]]+v[j];if t>f[i]then f[i]:=t;end;writeln(f[m]);end.这类型的题目应用挺广的(noip1996提高组第4题,noip2001普及组装箱问题,noip2005普及组采药等),下面一个例子,也是背包模型的简单转化。
货币系统(money)【问题描述】母牛们不但创建了他们自己的政府而且选择了建立了自己的货币系统。
他们对货币的数值感到好奇。
传统地,一个货币系统是由1,5,10,20或25,50,100的单位面值组成的。
母牛想知道用货币系统中的货币来构造一个确定的面值,有多少种不同的方法。
使用一个货币系统{1,2,5,10,..}产生18单位面值的一些可能的方法是:18×1,9×2,8×2+2×1,3×5+2+1等等其它。
写一个程序来计算有多少种方法用给定的货币系统来构造一个确定的面值。
【输入格式】货币系统中货币的种类数目是v(1≤v≤25);要构造的面值是n(1≤n≤10,000);第1行:二个整数,v和n;第2..v+1行:可用的货币v个整数(每行一个)。
凸多边形的最优三角剖分

t[3][5]=t[3][3]+t[4][5]+w(2,3,5)=17
(c)r=4时j=i+r-1 t[1][4]=t[1][1]+t[2][4]+w(0,1,4)=18 (v0v1v4和v2v3v4和v1v2v4)
t[2][5]=t[2][2]+t[3][5]+w(1,2,5)=25 (v2v3v4和v2v4v5和v1v2v5)
一个表达式的完全加括号方式对应于一棵完全二叉树, 人们称这棵二叉树为表达式的语法树。例如,与完全加括 号的矩阵链乘积((A1(A2A3))(A4(A5A6)))相对应的语法树如 图2(a)所示。
v0
A1 v1 A1 A2 A3 A4 A5 A2 A3 (b)
v5
A5 v4 A4 v3
v2 (a) 图2 表达式语法树与三角剖分的对应 图1(a)中凸多边形的三角剖分可用图2(b)所示的语法树来表示。该语法 树的根结点为边v0v6,三角剖分中的弦组成其余的内部结点。多边形中除 v0v6边外的每一条边是语法树的一个叶结点。树根v0v6是三角形v0v3v6的一 条边,该三角形将原多边形分为3个部分:三角形v0v3v6,凸多边形{v0 ,v1 ,… ,v3}和凸多边形{v3 ,v4 ,… ,v6}。三角形v0v3v6的另外两条边, 即弦v3v6和v0v3为根的两个儿子。以它们为根的子树分别表示凸多边形{v0 ,v1 ,… ,v3}和凸多边形{v3 ,v4 ,… ,v6}的三角剖分。
问题相关定义
(1)凸多边形的三角剖分:将凸多边形分割成互不相交
的弦的集合T。
(2)最优剖分:给定凸多边形P,以及定义在由多边形的
边和弦组成的三角形上的权函数w。要求确定该凸多边形
POJ 题目整理

初期:一.基本算法:(1)枚举. (poj1753,poj2965)(2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法.(4)递推.(5)构造法.(poj3295)(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)(3)最小生成树算法(prim,kruskal) (poj1789,poj2485,poj1258,poj3026)(4)拓扑排序 (poj1094)(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串 (poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书 page149):1.E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最长公共子序列) (poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)(poj1408,poj1584)(4)凸包. (poj2187,poj1113)中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索(1)最优化剪枝和可行性剪枝(2)搜索的技巧和优化 (poj3411,poj1724)(3)记忆化搜索(poj3373,poj1691)五.动态规划(1)较为复杂的动态规划(如动态规划解特别的施行商问题等) (poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)六.数学(1)组合数学:1.容斥原理.2.抽屉原理.3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).4.递推关系和母函数.(2)数学.1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)2.概率问题. (poj3071,poj3440)3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)(3)计算方法.1.0/1分数规划. (poj2976)2.三分法求解单峰(单谷)的极值.3.矩阵法(poj3150,poj3422,poj3070)4.迭代逼近(poj3301)(4)随机化算法(poj3318,poj2454)(5)杂题. (poj1870,poj3296,poj3286,poj1095)七.计算几何学.(1)坐标离散化.(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)(3)多边形的内核(半平面交)(poj3130,poj3335)(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)高级:一.基本算法要求:(1)代码快速写成,精简但不失风格(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)(2)保证正确性和高效性. poj3434二.图算法:(1)度限制最小生成树和第K最短路. (poj1639)(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解) (poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446) (3)最优比率生成树. (poj2728)(4)最小树形图(poj3164)(5)次小生成树.(6)无向图、有向图的最小环三.数据结构.(1)trie图的建立和应用. (poj2778)(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和在线算法(RMQ+dfs)).(poj1330)(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的目的).(poj2823)(4)左偏树(可合并堆).(5)后缀树(非常有用的数据结构,也是赛区考题的热点). (poj3415,poj3294)四.搜索(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法.(poj3131,poj2870,poj2286)五.动态规划(1)需要用数据结构优化的动态规划. (poj2754,poj3378,poj3017)(2)四边形不等式理论.(3)较难的状态DP(poj3133)六.数学(1)组合数学.1.MoBius反演(poj2888,poj2154)2.偏序关系理论.(2)博奕论.1.极大极小过程(poj3317,poj1085)2.Nim问题.七.计算几何学.(1)半平面求交(poj3384,poj2540)(2)可视图的建立(poj2966)(3)点集最小圆覆盖.(4)对踵点(poj2079)八.综合题.(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263) 以及补充Dp状态设计与方程总结1.不完全状态记录<1>青蛙过河问题<2>利用区间dp2.背包类问题<1> 0-1背包,经典问题<2>无限背包,经典问题<3>判定性背包问题<4>带附属关系的背包问题<5> + -1背包问题<6>双背包求最优值<7>构造三角形问题<8>带上下界限制的背包问题(012背包)3.线性的动态规划问题<1>积木游戏问题<2>决斗(判定性问题)<3>圆的最大多边形问题<4>统计单词个数问题<5>棋盘分割<6>日程安排问题<7>最小逼近问题(求出两数之比最接近某数/两数之和等于某数等等)<8>方块消除游戏(某区间可以连续消去求最大效益)<9>资源分配问题<10>数字三角形问题<11>漂亮的打印<12>邮局问题与构造答案<13>最高积木问题<14>两段连续和最大<15>2次幂和问题<16>N个数的最大M段子段和<17>交叉最大数问题4.判定性问题的dp(如判定整除、判定可达性等)<1>模K问题的dp<2>特殊的模K问题,求最大(最小)模K的数<3>变换数问题5.单调性优化的动态规划<1>1-SUM问题<2>2-SUM问题<3>序列划分问题(单调队列优化)6.剖分问题(多边形剖分/石子合并/圆的剖分/乘积最大)<1>凸多边形的三角剖分问题<2>乘积最大问题<3>多边形游戏(多边形边上是操作符,顶点有权值)<4>石子合并(N^3/N^2/NLogN各种优化)7.贪心的动态规划<1>最优装载问题<2>部分背包问题<3>乘船问题<4>贪心策略<5>双机调度问题Johnson算法8.状态dp<1>牛仔射击问题(博弈类)<2>哈密顿路径的状态dp<3>两支点天平平衡问题<4>一个有向图的最接近二部图9.树型dp<1>完美服务器问题(每个节点有3种状态)<2>小胖守皇宫问题<3>网络收费问题<4>树中漫游问题<5>树上的博弈<6>树的最大独立集问题<7>树的最大平衡值问题<8>构造树的最小环转一个搞ACM需要的掌握的算法.要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来.适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红, 发挥自己的长处,这才是重要的.第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来.1.最短路(Floyd、Dijstra,BellmanFord)2.最小生成树(先写个prim,kruscal要用并查集,不好写)3.大数(高精度)加减乘除4.二分查找. (代码可在五行以内)5.叉乘、判线段相交、然后写个凸包.6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.8. 调用系统的qsort, 技巧很多,慢慢掌握.9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。
2022年职业考证-软考-软件设计师考试全真模拟专项剖析AB卷(带答案)试卷号:11
2022年职业考证-软考-软件设计师考试全真模拟专项剖析AB卷(带答案)一.综合题(共15题)1.单选题Python 语言的特点不包括()。
问题1选项A.跨平台、开源B.编译型C.支持面向对象程序设计D.动态编程【答案】B【解析】本题考查python相关问题。
python语义的特点:跨平台、开源、简单易学、面向对象、可移植性、解释性、开源、高级语言、可扩展性、丰富的库、动态编程等等综上所述B选项错误,python不是编译型语言,而是解释型语言。
2.案例题阅读下列说明和代码,回答问题1和问题2,将解答写在答题纸的对应栏内。
【说明】凸多边形是指多边形的任意两点的连线均落在多边形的边界或内部。
相邻的点连线落在多边形边界上,称为边;不相邻的点连线落在多边形内部,称为弦。
假设任意两点连线上均有权重,凸多边形最优三角剖分问题定义为:求将凸多边形划分为不相交的三角形集合,且各三角形权重之和最小的剖分方案。
每个三角形的权重为三条边权重之和。
假设N个点的凸多边形点编号为V1,V2,……,VN,若在VK处将原凸多边形划分为一个三角形V1VkVN,两个子多边形V1,V2,…,Vk和Vk,Vk+1,…VN,得到一个最优的剖分方案,则该最优剖分方案应该包含这两个子凸边形的最优剖分方案。
用m[i][j]表示带你Vi-1,Vi,…Vj构成的凸多边形的最优剖分方案的权重,S[i][j]记录剖分该凸多边形的k值。
则其中:W(Vi-1VkVj)=Wi-1,k+Wk,j+Wj,i-1为三角形Vi-1VkVj的权重,Wi-1,k,Wk,j,Wj,i-1分别为该三角形三条边的权重。
求解凸多边形的最优剖分方案,即求解最小剖分的权重及对应的三角形集。
[C代码]#include<stdio.h>#define N 6 //凸多边形规模int m[N+1] [N+1]; //m[i][j]表示多边形Vi-1到Vj最优三角剖分的权值int S[N+1] [N+1]; //S[i][j]记录多边形Vi-1到Vj最优三角剖分的k值int W[N+1] [N+1]; //凸多边形的权重矩阵,在main函数中输入/*三角形的权重a,b,c,三角形的顶点下标*/int get_ triangle_weight(int a,int b,int c){return W[a][b]+W[b][c]+W[c][a];}/*求解最优值*/void triangle_partition(){int i,r,k,j;int temp;/*初始化*/for(i=1;i{ /*r为子问题规模*/for(i=1;k {(2);m[i][j]= m[i][j]+m[i+1][j]+get_triangle_weight(i-1,i,j); /*k=j*/S[i][j]=i;for(k=j+1;k { /*计算 [i][j]的最小代价*/temp=m[i][k]+m[k+1][j]+ge_triangle_ weight(i-1,k,j);if((3)){ /*判断是否最小值*/m[i][j]=temp;S[i][j]=k;}}}}}/*输出剖分的三角形i,j:凸多边形的起始点下标*/void print_triangle(int i,int j){if(i==j) return;print_triangle(i,S[i][j]);print_ triangle((4));print(“V%d- -V%d- -V%d\n“,i-1,S[i][j],j);}【问题1】(8分)根据题干说明,填充C代码中的空(1)~(4)。
Chapter-4 动态规划
M i r r
i
i 1
1 i n
M i , j M i M i 1 M k 1 M k M k 1 M j 1 M j
C[i , j ] C[ i.k 1] C[ k , j ]
最长公共子序列问题
• 给定两个定义在字符集∑上的字符串A和B,长度分别 为n和m,现在要求它们的最长公共子序列的长度值 (最优值),以及对应的子序列(最优解) 。 • 子序列
A a1a2 an 的一个子序列是形如下式的一个字符串: ai1 ai2 ain ,其中
1 i1 i2 ik n
C[1,3]=320 C[2,3]=240 (M2 M3) C[3,3] =0 (M3)
C[1,4]=620 C[2,4]=640 (M2) (M3M4) C[3,4]=240 (M3M4) C[4,4] =0 (M4)
C[1,5]=348 C[2,5]=248 C[3,5]=168 C[4,5]=120 (M4 M5) C[5,5] =0 (M5)
4n f (n) ( 1.5 ) n
结论:穷举法复杂度太高
南京理工大学
使用动态规划法:
M1 M 2 M3 M n r1 , r2 , r3 ,rn , rn1
Mi, j Mi Mi1 M j 1 M j
C[i, j ] :计算 Mi, j 所需的最小乘法次数。 i 1, j n 时,原问题得解。
f (k ) f ( nk )
f ( n) f ( k ) f ( n k )
k 1
n 1
f (1) 1, f (2) 1, f (3) 2
1 n 1 f ( n ) C2 n 2 n
凸多边形划分卡特兰数
凸多边形划分卡特兰数凸多边形是一个有着所有内角均小于180度的多边形。
凸多边形的划分是指将一个凸多边形划分为许多小的三角形的过程。
而卡特兰数则用于计算凸多边形的划分数量。
本文将介绍凸多边形划分和卡特兰数的相关知识。
凸多边形的划分有许多应用,比如计算凸多边形内部的路径数量、计算凸多边形中不相交的三角形数量等。
卡特兰数则是一种用于计算各种组合问题的数学工具。
卡特兰数由法国数学家Eugene Charles Catalan在19世纪提出,被广泛应用于组合数学和计算几何学领域。
卡特兰数的计算公式为Cn=(2n)!/((n+1)!*n!),其中n为凸多边形的边数。
具体来说,Cn表示n个三角形的凸多边形划分数量。
例如,一个四边形可以有两种划分方式:一种是将四边形对角线相交的点连接,形成两个三角形;另一种是将四边形的一条边与其余三条边相连,形成四个三角形。
因此,C4=2。
卡特兰数具有一些有趣的性质。
首先,卡特兰数是递归定义的,即Cn可以由C0、C1、C2...C(n-1)计算得出。
其次,卡特兰数满足递推关系Cn=C0C(n-1)+C1C(n-2)+...+C(n-1)C0。
最后,卡特兰数的增长速度非常快,当n增大时,Cn的增长呈指数级。
凸多边形划分卡特兰数在计算几何学和组合数学中有广泛的应用。
它们可以用于解决各种凸多边形相关的问题,如计算凸多边形的划分数量、计算凸多边形内部路径的数量以及计算凸多边形中不相交的三角形数量等。
卡特兰数的计算公式简单明了,但在大规模问题上的计算可能会非常耗时和复杂。
总而言之,凸多边形划分卡特兰数是一种重要的数学工具,广泛应用于计算几何学和组合数学领域。
它们能够帮助我们解决各种凸多边形相关的问题,并且具有一些有趣的性质。
研究和理解凸多边形划分卡特兰数对于深入了解组合数学的应用和挑战具有重要意义。
凸多边形最优三角剖分算法c语言
凸多边形最优三角剖分算法c语言以凸多边形最优三角剖分算法C语言为标题凸多边形是指所有内角都小于180度的多边形。
在凸多边形中,有许多不同的三角剖分方式,而最优三角剖分算法则是指找到一种三角剖分方式,使得剖分后的三角形形状合理,并且剖分后的三角形的总面积最小。
在本文中,我们将介绍一种基于C语言的凸多边形最优三角剖分算法。
1. 凸多边形的表示为了方便计算,我们首先需要将凸多边形表示成计算机能够理解的数据结构。
一种常用的方法是使用顶点数组来表示凸多边形的顶点坐标。
假设凸多边形有n个顶点,我们可以用一个长度为n的顶点数组来表示。
例如,对于一个三角形,可以定义如下的顶点数组:```ctypedef struct {float x;float y;} Point;Point polygon[] = {{0.0, 0.0},{1.0, 0.0},{0.5, 1.0}};```2. 最优三角剖分算法的思路凸多边形最优三角剖分算法的基本思路是通过动态规划的方法逐步计算出最优解。
具体而言,我们可以定义一个二维数组dp,其中dp[i][j]表示从顶点i到顶点j的最小三角剖分面积。
然后,我们可以通过填充dp数组来逐步计算出最优解。
填充dp数组的方法如下:- 初始化dp数组的对角线元素为0,即dp[i][i]=0- 对于每个子问题dp[i][j],我们可以通过枚举所有可能的中间顶点k来计算dp[i][j]的值。
具体而言,我们可以遍历所有i<k<j的k值,计算出以顶点i、k和j作为三角形顶点的三角形面积,并将其加入到dp[i][j]中。
然后,我们还需要遍历所有可能的k值,找到使得dp[i][k]+dp[k][j]+以顶点i、k和j作为顶点的三角形面积最小的k 值,并将其作为dp[i][j]的值。
这样,我们就可以逐步填充dp数组,最终得到最优解。
3. 算法实现```cfloat min(float a, float b) {return a < b ? a : b;}float triangleArea(Point a, Point b, Point c) {return fabs((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) / 2.0;}float optimalTriangulation(Point polygon[], int n) {float dp[n][n];for (int i = 0; i < n; i++) {dp[i][i] = 0.0;}for (int len = 2; len < n; len++) {for (int i = 0; i < n - len; i++) {int j = i + len;dp[i][j] = INFINITY;for (int k = i + 1; k < j; k++) {float area = triangleArea(polygon[i], polygon[k], polygon[j]);dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + area);}}}return dp[0][n - 1];}```4. 算法分析最优三角剖分算法的时间复杂度为O(n^3),其中n为凸多边形的顶点数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态规划【凸多边形三角划分】
【凸多边形三角划分】
给定一个具有N(N<50)个顶点(从l到N编号)的凸多边形,每个顶点的权均已知。
问如何把这个凸多边形划分成N-2个互不相交的三角形,使得这些三角形顶点的权的乘积之和最小。
【输入格式】
第一行为顶点数N;
第二行为N个顶点(从1到N)的权值。
【输出格式】
最小的和的值。
【输入样例】
5
121 122 123 245 231
【输出样例】
12214884
二、试题分析
这是一道很典型的动态规划问题。
设F[I,J](I<J)表示从顶点I到顶点J的凸多边形三角剖分后所得到的最大乘积,我们可以得到下面的动态转移方程:
F[I,J]=Min{F[I,K]+F[K,J]+S[I]*S[J]*S[K]} (I<K<J)
目标状态为:F[1,N]
但我们可以发现,由于这里为乘积之和,在输入数据较大时有可能超过长整形甚至实形的范围,所以我们还需用高精度计算,但这是大家的基本功,程序中就没有写了,请读者自行完成。
三、参考程序
Var S :Array[1..50] Of Integer;
F :Array[1..50,1..50] Of Comp;
D :Array[1..50,1..50] Of Byte;
N :Integer;
Procedure Init; (输入数据)
Var I :Integer;
Begin
Readln(N);
For I:=1 To N Do Read(S[I]);
End;
Procedure Dynamic; (动态规划)
Var I,J,K :Integer;
Begin
For I:=1 To N Do
For J:=I+1 To N Do F[I,J]:=Maxlongint; (赋初始值)For I:=N-2 Downto 1 Do
For J:=I+2 To N Do
For K:=I+1 To J-1 Do
If (F[I,J]>F[I,K]+F[K,J]+S[I]*S[J]*S[K]) Then
Begin
F[I,J]:=F[I,K]+F[K,J]+S[I]*S[J]*S[K];
D[I,J]:=K; (记录父节点)
End;
End;
Procedure Print(I,J:Integer); (输出每个三角形)Begin
If J=I+1 Then Exit;
Write(',',I,' ',J,' ',D[I,J]);
Out(I,D[I,J]);
Out(D[I,J],J);
End;
Procedure Out; (输出信息)
Begin
Assign(Output,'Output.Txt'); Rewrite(Output);
Writeln('The minimum is :',F[1,N]:0:0);
Writeln('The formation of ',N-2,' triangle:');
Write(1,' ',N,' 'D[1,N]);
Out(1,D[1,N]); Out(D[1,N],N); Close(Output); End;
Begin (主程序)Init; Dynamic;
Out;
End.。