Description

给你2个矩阵A、B,我们使用标准的矩阵相乘定义C=AB如下: A数组中栏(column)的数目一定要等于B数组中列(row)的数目才可以做此2数组的相乘。若我们以rows(A),columns(A)分 别代表A数组中列及栏的数目,要计算C数组共需要的乘法的数目为:rows(A)columns(B)columns(A)。例如:A数组是一个 10x20的矩阵,B数组是个20x15的矩阵,那么要算出C数组需要做101520,也就是3000次乘法。 要计算超过2个以上的矩阵相乘就得决定要用怎样的顺序来做。

例如:X、Y、Z都是矩阵,要计算XYZ的话可以有2种选择:(XY)Z 或者 X(YZ)。

假设X是5x10的数组,Y是10x20的数组,Z是20x35的数组,那个不同的运算顺序所需的乘法数会有不同:

(XY)Z

  • 5 * 20 * 10 = 1000次乘法完成(XY),并得到一5x20的数组。
  • 5 * 35 * 20 = 3500次乘法得到最后的结果。
  • 总共需要的乘法的次数:1000+3500=4500。

X(YZ)

  • 10 * 35 * 20 = 7000次乘法完成(YZ),并得到一10x35的数组。
  • 5 * 35 * 10 = 1750次乘法得到最后的结果。
  • 总共需要的乘法的次数:7000 +1750 = 8750。

很明显的,我们可以知道计算(XY)Z会使用较少次的乘法。 这个问题是:给你一些矩阵,你要写一个程序来决定该如何相乘的顺序,使得用到乘法的次数会最少。

Input

含有多组测试数据,每组测试数据的第一列,含有1个整数N(N <= 10)代表有多少个数组要相乘。接下来有N对整数,代表一数组的列数及栏数。这N个数组的顺序与要你相乘的数组顺序是一样的。N=0代表输入结束。请参考Sample Input。

Output

每组测试数据输出一列,内容为矩阵相乘的顺序(以刮号来表示)使得所用的乘法次数最小。如果有不只一组答案,输出任一组均可。请参考Sample Output。

Sample Input

  1. 3
  2. 1 5
  3. 5 20
  4. 20 1
  5. 3
  6. 5 10
  7. 10 20
  8. 20 35
  9. 6
  10. 30 35
  11. 35 15
  12. 15 5
  13. 5 10
  14. 10 20
  15. 20 25
  16. 0

Sample Output

  1. Case 1: (A1 x (A2 x A3))
  2. Case 2: ((A1 x A2) x A3)
  3. Case 3: ((A1 x (A2 x A3)) x ((A4 x A5) x A6))

递归关系:

$$ m[i][j] = \begin{cases} 0 &\ i == j \\ \min_{i \le k \lt j} \{ m[i][k] + m[k+1][j] + p_{i-1}*p_k*p_j \} &\ i<j \end{cases} $$

数组m[n][n]存储最优值

数组s[n][n]存储最优时分割的位置

  1. import java.util.Scanner;
  2. public class Main {
  3. static int count = 0;
  4. public static void main(String[] args) {
  5. Scanner sc = new Scanner(System.in);
  6. int p[], m[][], s[][];
  7. while (sc.hasNextInt()) {
  8. int n = sc.nextInt();
  9. if (n == 0)
  10. break;
  11. p = new int[n + 1];
  12. m = new int[n + 1][n + 1];
  13. s = new int[n + 1][n + 1];
  14. for (int i = 0; i < n; i++) {
  15. p[i] = sc.nextInt();
  16. p[i + 1] = sc.nextInt();
  17. }
  18. matrixChain(p, m, s);
  19. System.out.printf("Case %d: ", ++count);
  20. print(1, n, s);
  21. System.out.print('\n');
  22. // printmAnds(n, m, s);
  23. }
  24. sc.close();
  25. }
  26. public static void matrixChain(int p[], int m[][], int s[][]) {
  27. int n = p.length - 1;
  28. for (int i = 1; i <= n; i++)
  29. m[i][i] = 0;
  30. for (int r = 2; r <= n; r++) {
  31. for (int i = 1; i <= n - r + 1; i++) {
  32. int j = i + r - 1;
  33. m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
  34. s[i][j] = i;
  35. for (int k = i + 1; k < j; k++) {
  36. int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
  37. if (t < m[i][j]) {
  38. m[i][j] = t;
  39. s[i][j] = k;
  40. }
  41. }
  42. }
  43. }
  44. }
  45. public static void print(int i, int j, int s[][]) {
  46. if (i == j) {
  47. System.out.print("A" + i);
  48. return;
  49. }
  50. else {
  51. System.out.print("(");
  52. print(i, s[i][j], s);
  53. System.out.print(" x ");
  54. print(s[i][j] + 1, j, s);
  55. System.out.print(")");
  56. }
  57. }
  58. // public static void printmAnds(int n, int m[][], int s[][]){
  59. // System.out.printf("m[%d][%d]: \n", n, n);
  60. // for (int i = 1; i <= n; i++) {
  61. // System.out.print(m[i][1]);
  62. // for (int j = 2; j <= n; j++) {
  63. // System.out.print("\t" + m[i][j]);
  64. // }
  65. // System.out.print('\n');
  66. // }
  67. //
  68. // System.out.printf("s[%d][%d]: \n", n, n);
  69. // for (int i = 1; i <= n; i++) {
  70. // System.out.print(s[i][1]);
  71. // for (int j = 2; j <= n; j++) {
  72. // System.out.print("\t" + s[i][j]);
  73. // }
  74. // System.out.print('\n');
  75. // }
  76. // }
  77. }

算法:矩阵连乘(Java)动态规划的更多相关文章

  1. 【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)

    [BZOJ1009]GT考试(KMP算法,矩阵快速幂,动态规划) 题面 BZOJ 题解 看到这个题目 化简一下题意 长度为\(n\)的,由\(0-9\)组成的字符串中 不含串\(s\)的串的数量有几个 ...

  2. TextRank算法提取关键词的Java实现

    转载:码农场 » TextRank算法提取关键词的Java实现 谈起自动摘要算法,常见的并且最易实现的当属TF-IDF,但是感觉TF-IDF效果一般,不如TextRank好. TextRank是在 G ...

  3. 【BZOJ4000】[TJOI2015]棋盘(矩阵快速幂,动态规划)

    [BZOJ4000][TJOI2015]棋盘(矩阵快速幂,动态规划) 题面 BZOJ 洛谷 题解 发现所有的东西都是从\(0\)开始编号的,所以状压只需要压一行就行了. 然后就可以随意矩乘了. #in ...

  4. 【BZOJ4832】抵制克苏恩(矩阵快速幂,动态规划)

    [BZOJ4832]抵制克苏恩(矩阵快速幂,动态规划) 题面 BZOJ 题解 一模一样 #include<iostream> #include<cstdio> using na ...

  5. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

  6. 【BZOJ1898】[ZJOI2005]沼泽鳄鱼(矩阵快速幂,动态规划)

    [BZOJ1898][ZJOI2005]沼泽鳄鱼(矩阵快速幂,动态规划) 题面 BZOJ 洛谷 题解 先吐槽,说好了的鳄鱼呢,题面里面全是食人鱼 看到数据范围一眼想到矩乘. 先不考虑食人鱼的问题,直接 ...

  7. 算法笔记_071:SPFA算法简单介绍(Java)

    目录 1 问题描述 2 解决方案 2.1 具体编码   1 问题描述 何为spfa(Shortest Path Faster Algorithm)算法? spfa算法功能:给定一个加权连通图,选取一个 ...

  8. 常用的排序算法介绍和在JAVA的实现(二)

    一.写随笔的原因:本文接上次的常用的排序算法介绍和在JAVA的实现(一) 二.具体的内容: 3.交换排序 交换排序:通过交换元素之间的位置来实现排序. 交换排序又可细分为:冒泡排序,快速排序 (1)冒 ...

  9. 算法笔记_081:蓝桥杯练习 算法提高 矩阵乘法(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要将它们依次相乘,只能使用结合率,求最 ...

随机推荐

  1. oozie.action.hadoop.LauncherException: IO error Connection timed out: no further information

    本文主要针对使用CDH平台的HUE时候碰到两类问题,最终问题并没有得到很好的解决,只是提供了一种绕行方式,欢迎知道的朋友补充. ## **NO 1: HUE执行jar包** > 第一种报错 or ...

  2. SQL 使用openquery进行跨库操作

    摘自:http://www.cnblogs.com/aji88/archive/2009/11/06/1597263.html 对给定的链接服务器执行指定的传递查询.该服务器是 OLE DB 数据源. ...

  3. Linux运维学习第二周记

    1 梨花淡白柳深青, 2 柳絮飞时花满城. 3 惆怅东栏一株雪, 4 人生看得几清明. 老牛望春满地绿! 第二周直接要起飞了! 仍然是最基础最基础的东西,但也是特别多,的别重要! 第二周学记 1.Li ...

  4. 记一次JFormDesigner破解问题idea版本号2020.2.2

    第一步: 首先idea 2020.2.2下载插件JFormDesigner插件(软件版本7.0.1); 第二步:下载注册机(以上两步软件打包 在百度云) 第三步:点击 redister注册 第四步:打 ...

  5. 学python,大概要多久?

    都让开!本人文科生,自学Python 2年半,作为一个曾经完全0基础,啥都不懂纯靠自学学会python的文科生,有一些不成熟的小建议可以分享一下. 首先不要觉着编程难,只要你认识26个英文字母,有一点 ...

  6. 使用Vue简单的写组件的UI库

    初始化项目vue create nature-ui 在根目录下面创建一个文件目录放置组件(我这里的创建packages) packages 目录下面创建个个组件的名称并创建index.js(用于输出所 ...

  7. java数据结构-07栈

    一.什么是栈 栈是一种线性结构,栈的特点就是先进后出(FILO):就像弹夹装子弹一样,最先压进去的在最底下,最后才被射出.  二.相关接口设计  三.栈的实现 栈可以用之前的数组.链表等设计,这里我使 ...

  8. java开发-前后端分离

    众所周知,做java开发是后端的开发,我们时常与前端打交道,但更加注重后端代码的实现,前台的页面都是由前端开发人员做的,那么,是怎么做到前后端分离的呢? 首先,是后端的开发, 在mapper层:Stu ...

  9. java POI Excel 单元格样式

    正如Html需要CSS一样,我们的POI生成的Excel同样需要样式才能更完美的表现我们的数据.下面还是从简单的例子出发,学习和了解POI的样式设计. 一.我的位置. 1 package com.my ...

  10. Luogu P3757 [CQOI2017]老C的键盘

    题目描述 老C的键盘 题解 显然对于每个数 x 都有唯一对应的 \(x/2\) , 然而对于每个数 x 却可以成为 \(x*2\) 和 \(x*2+1\) 的对应数 根据这一特性想到了啥??? 感谢l ...