1 问题描述
注意:3≤顶点个数≤50
2 问题分析
1.利用动态规划解题如何存储中间结果?
题目中是让求解三角形三顶点乘积的最小值,对于多边形中的三个不同的顶点,我们分别记作A,B,C.那么我们可以固定其中的两个顶点A,B,然后遍历A,B间的所有顶点,去获取最小的乘积值.所以我们使用二维数组来存储动态规划子问题的解.
2.我们需要实现一个什么样的函数?
我们实现的函数需要能够保证对于传递给它的数组(即多边形),能过正确返回得分的最小值.同时我们需要确定多边形中找到的分析1中的那两个点.
确定函数的参数为(数组,数组大小,起点,终点)
3.如何获得最小的结果值?
对于起点和终点,我们需要从起点后的一个点,遍历到终点前的一个点,如果满足
n
u
m
s
[
s
t
a
r
t
]
∗
n
u
m
s
[
i
]
∗
n
u
m
[
e
n
d
]
<
n
u
m
s
[
n
o
w
]
nums[start] * nums[i] * num[end] < nums[now]
nums[start]∗nums[i]∗num[end]<nums[now],那么,我们就把这个最小值存入到二位数组中.
n
u
m
s
[
n
o
w
]
nums[now]
nums[now]我们可以建立一个变量来记录.
4.二维数组的初始值?
最开始的时候时候还没有开始计算,所以二维数组中的所有值都是0.
3 变量设计
二维数组:我们用A[51][51]来存储所有的子问题的结果.
n u m s [ n o w ] nums[now] nums[now]:我们直接用变量result来记录这个最终结果.
中间结果:我们使用临时变量tmp来存储每次计算结果
-------------即
n
u
m
s
[
s
t
a
r
t
]
∗
n
u
m
s
[
i
]
∗
n
u
m
[
e
n
d
]
nums[start] * nums[i] * num[end]
nums[start]∗nums[i]∗num[end]
循环变量:由于函数参数传入的是起点和终点,那我们需要计算位于起点和终点之间的点的个数 n n n.同时我们用 i i i来作为遍历时候的标识.
函数: d p ( i n t − ∗ A , i n t − A S i z e , i n t − s t a r t , i n t − e n d ) dp(int-*A, int-ASize, int-start, int-end) dp(int−∗A,int−ASize,int−start,int−end),这里取动态规划的缩写来作为函数名.每次调用这个函数我们就实现了求得起点为start终点为end的最小值.函数内部的细节将会写在代码的注释中.
3 代码实现
unsigned int res_cache[51][51] = {0};
unsigned int dp(int *A, int Asize, int start, int end)
{
int i;
// 这个记录每次传递进函数内部的点的个数
int n = end - start;
// 这个变量用来记录结果值result
unsigned int res;
// 这个用来充当临时变量
unsigned int tmp;
// 两个点不能组成三角形
if(n<2) return 0;
// 如果已经有了计算结果,那么直接返回就行
if(res_cache[start][end]>0) return res_cache[start][end];
// 当n==2的时候,说明一共有三个点,0-1-2
if(n==2)
{ // 这个计算结果一定就是这三个点的计算结果了,因为没得选
res = A[start] * A[start+1] * A[end];
// 将结果值赋给数组
res_cache[start][end] = res;
return res;
}
// 这里一定要写-1,因为二位函数的赋值为0,如果不写-1的话
//就无法进行了. ( 0 == 0 ) //这里不是颜文字!!
res = -1;
// 注意 i 从start 的下一个顶点开始
for(i=start+1; i<end; i++)
{
// 先计算乘积值
tmp = A[start] * A[i] * A[end];
// 如果i等于最后一个顶点的前一个顶点
if(i == end-1)
{ // 那么我们进行划分后,就形成了一条新的边start-i
// 为什么没有形成 i - end 边呢?
// 因为 i - end - start 形成了闭循环.
// 这条边也需要去寻找属于它的最小值
tmp += dp(A, Asize, start, i);
}
else
{
// 这个情况下
// 我们的划分形成了两条新的边 start-i 和 i - end
// 我们还要去寻找这两条边的最小值
tmp += dp(A, Asize, start, i) + dp(A, Asize, i ,end);
}
if(res > tmp)
{
res = tmp;
}
}
// 最后将记录的最小res返回给二维数组
res_cache[start][end] = res;
return res;
}
int minScoreTriangulation(int* A, int ASize)
{
// memset函数简介
// 对[参数1]位置后面[参数3]个字节的空间置成[参数2]
memset(res_cache, 0, sizeof(res_cache));
return dp(A, ASize, 0, ASize-1);
}