继续上一篇的高级数据结构与算法的期末速成
2.3动态规划之凸多边形最优三角剖分
问题描述:
多边形的边除了顶点没有别的交点,这就是一个简单的多边形。简单的多边形可以将平面分为三个部分:被包围在多边形内的所有点构成了多边形的内部,多边形本身构成多边形的边界,平面上其余被多边形包围的点构成了多边形的外部。
当一个简单多边形和其内部构成一个凸集时,则称该简单多边形为一个凸多边形。
用多边形顶点的逆时针序列表示凸多边形,即 P = v 0 , v 1 , … , v n − 1 P={v_0,v_1,…,v_{n-1}} P=v0,v1,…,vn−1表示具有n条边的凸多边形。
若 v i 与 v j v_i与v_j vi与vj是多边形上不相邻的2个顶点,则线段 v i v j v_iv_j vivj称为多边形的一条弦。
弦将多边形分割成2个多边形 v i , v i + 1 , … , v j {v_i,v_{i+1},…,v{j}} vi,vi+1,…,vj和 v j , v j + 1 , … v n − 1 {v_j,v_{j+1},…v_{n-1}} vj,vj+1,…vn−1。
多边形的三角剖分是将多边形分割成互不相交的三角形的**弦**的集合T.
给定凸多边形P,以及定义在由多边形的边和弦组成的三角形上的权函数w。要求确定该凸多边形的三角剖分,使得即该三角剖分中诸三角形上权之和为最小。
输入描述:
首先输入一个正整数 n n n表示顶点数,之后你是弦的信息按照a b weight
的格式给出
输出:
三角剖分中诸三角形上权之和为最小。
(注意:这个题没有找链接,也没找示例)
代码不一定对(🤣🤣🤣🤣)这个题只供参考,代码不对.我不中嘞.
思路:
证明最优子结构就不证明了,两个弦就可以把问题分为两个子问题,最优解就是
w e i g h t ( i , k ) + w e i g h t ( k , j ) + d p [ i ] [ k − 1 ] + d p [ k + 1 ] [ j ] weight(i,k)+weight(k,j)+dp[i][k-1]+dp[k+1][j] weight(i,k)+weight(k,j)+dp[i][k−1]+dp[k+1][j]
这个就是和上一个矩阵连乘问题比较相似.
代码示例:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int weight[n+2][n+2]={
0};
int ans=INT_MAX;
int dp[n+2][n+2];
memset(dp,0,sizeof dp);
for(int i=0;i<n*n-3*n;i++)
{
int a,b,c;
cin>>a>>b>>c;
weight[a][b]=c;
}
for(int i=1;i<=n;i++)
dp[i][i]=0;
for(int r=2;r<=n;r++)
{
for(int i=1;i<=n-r+1;i++)
{
int j=i+r-1;
dp[i][j]=dp[i+1][j]+weight[i-1][i]+weight[i][j];
for(int k=i+1;k<i+r-1;k++)
{
dp[i][j]=min(dp[i][j],
dp[k][j]+weight[i-1][k]+weight[i][j]);
}
}
}
cout<<dp[1][n]<<endl;
return 0;
}
2.4动态规划之石子合并
问题描述:
设有 N N N堆石子排成一排,其编号为 1 , 2 , 3 , . ⋅ ⋅ , N 1,2,3,.··,N 1,2,3,.⋅⋅,N。
每堆石子有一定的质量,可以用一个整数来描述,现在要将这$ N $堆石子合并成为一堆。
每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同。
例如有 4 堆石子分别为1 3 5 2,我们可以先合并1、2 堆,代价为 4,得到4 5 2,又合并1、2 堆,代价为9,得到9 2,再合并得到11,总代价为 4+9+11=24;
如果第二步是先合并 2、3堆,则代价为 7,得到4 7,最后一次合并代价为 11,总代价为
4 + 7 + 11 = 22。
问题是:找出一种合理的方法,使总的代价最小,输出最小代价。
输入格式:
第一行一个数 N 表示石子的堆数 N。
第二行 N 个数,表示每堆石子的质量(均不超过1000)。
输出格式:
输出一个整数,表示最小代价。
思路分析:
最后一次合并一定是左边连续的一部分和右边连续的一部分进行合并,之后就把整个石头堆合并是一个定值,可以使用前缀和快速得到某段区间的和.
状态表示: f [ i ] [ j ] f[i][j] f[i][j]表示 从 i 到 j 从i到j 从i到j这一段石子合并成一堆的方案的最小代价
则易得状态转移方程为:
y ( x ) = { min i ≤ k ≤ j − 1 { f [ i ] [ k ] + f [ k + 1 ] [ j ] + s [ j ] − s [ i − 1 ] } , i < j , 0 , i = j . y(x) = \begin{cases} \displaystyle \min_{\,i \le k \le j-1} \bigl\{\,f[i][k] \;+\; f[k+1][j] \;+\; s[j] - s[i-1] \bigr\}, & i < j, \\[1ex] 0, & i = j. \end{cases} y(x)=⎩
⎨
⎧i≤k≤j−1min{