这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
题目
输入一个数组**P**如P={30,35,15,5,10,20},大小为n=5,相应的矩阵为:A1<30,35> ,A2<35,15> ,A3<15,5> ,A4<5,10> ,A5<10,20>
计算A1到A5矩阵相乘的最优解
方法一共有两种:
第一种:分治算法
使用分治算法的步骤为
1. 求出最小子问题解
2. 分解问题
3. 找递归方程式
4. 合并问题
复制代码
套用到本题中,题目要求为计算A1到A5矩阵相乘的最优解 **最小子问题:**m[i,i] = 0 分解问题: 分割为两个矩阵相乘
递归方程式 :当 l = r 时 sum = 0
当l < r 时 sum = sum(l,l+1)
合并问题: min[i] = sum(p,l,l + i)+sum(p,l+i+1,r)+p[l-1] * p[i+l] * p[r];
代码如下:
public class Matriz {
public static void main(String[] args) throws ParseException {
long time = System.nanoTime();
int n = 100;
int [][]num = new int[n][n];
int p[] = {30,35,15,5,10,20,30,35,15,5,10,20,30,35,15,5,10,20,30,35,15,5,10,20,30,35,15,5,10,20};
int sum = sum(p, 1, 6);
Date endDate = new Date();
long endTime = System.nanoTime();
System.out.println(sum);
System.out.println(endTime -time + "ns");
}
private static int sum(int[] p, int l, int r) {
if (l == r) return 0;
int min[] = new int[100];
for (int i = 0; l+i < r ; i++) {
min[i] = sum(p,l,l + i)+sum(p,l+i+1,r)+p[l-1]*p[i+l]*p[r];
}
int min_ = min[0];
for (int i = 0; l+i < r; i++) {
if (min_ > min[i]){
min_ = min[i];
}
}
return min_;
}
}
复制代码
第二种:动态规划
为什么要使用动态规划呢?
从第一种方法可以看出,分治算法虽然使用方便,也比较好理解,和想出。但是它也有一个缺点,会进行重复运算。比如A1和A2两个矩阵相乘,在A1到A5矩阵相乘的递归中会重复计算4次,那如果是A1到A100呢就会重复计算99次,如果数字在大一点,重复计算的次数就会越来越大。为了避免这个问题我们可以使用动态规划。动态规划的优点就是会在计算一次最优解后,会记录下来,已供后面使用,这样就避免了重复运算。
在这个问题里我们只要解决两问题就可以了
- 填表:填表我们采用斜向遍历上三角来填表
- 计算最小值:则使用公式 min[i] = num[ k ][ k + i ]+num[k+i+1][j]+p[k]* p[i+k+1] *p[j+1];来分别计算矩阵相乘的结果,最后比较求出最小值
import java.util.Scanner;
/**
* 矩阵相乘
*
*/
public class Test01 {
public static int min(int [] p,int k,int j,int num[][]){
int min[] = new int[100];
for (int i = 0; k+i < j ; i++) {
min[i] = num[k][k+i]+num[k+i+1][j]+p[k]*p[i+k+1]*p[j+1];
}
int sum = min[0];
for (int i = 0; k+i < j; i++) {
if (sum > min[i]){
sum = min[i];
}
}
return sum;
}
public static void main(String[] args) {
// System.out.println("请输入矩阵大小:");
// Scanner scanner = new Scanner(System.in);
int n = 6;
int [][]num = new int[n][n];
// 49 54
int p[] = {30,35,15,5,10,20,20};
for (int i = 0; i < n; i++) {
for (int j = 0; j < (n-i); j++) {
if (j == j+i){
num[j][j+i] = 0;
}else {
num[j][j+i] = min(p,j,j+i,num);
}
System.out.print(num[j][j+i]+" ");
}
System.out.println("");
}
}
}
复制代码
近期评论