【发布时间】:2016-12-02 01:40:50
【问题描述】:
我知道一个可以使用 DP 解决的问题,可以通过制表(自下而上)方法或记忆化(自上而下)方法来解决。我个人发现记忆是简单甚至有效的方法(只需分析即可获得递归公式,一旦获得递归公式,就可以轻松地将暴力递归方法转换为存储子问题的结果并重用它。)唯一的问题是我在这种方法中面临的是,我无法从我按需填写的表中构造实际结果。
例如,在Matrix Product Parenthesization problem 中(决定在矩阵上执行乘法的顺序以使乘法成本最小)我能够计算无法在算法中生成顺序的最小成本。
例如,假设 A 是 10 × 30 矩阵,B 是 30 × 5 矩阵,C 是 5 × 60 矩阵。那么,
(AB)C = (10×30×5) + (10×5×60) = 1500 + 3000 = 4500 operations
A(BC) = (30×5×60) + (10×30×60) = 9000 + 18000 = 27000 operations.
在这里我可以得到 27000 的最低成本,但无法获得 A(BC) 的订单。
我用过这个。假设 F[i, j] 表示与 Ai.....Aj 相乘所需的最少乘法次数,并且给出了一个数组 p[],它表示矩阵链,使得第 i 个矩阵 Ai 的维数为 p[i-1 ] xp[i]。所以
0 if i=j F[i,j]= min(F[i,k] + F[k+1,j] +P_i-1 * P_k * P_j where k∈[i,j)
下面是我创建的实现。
#include<stdio.h>
#include<limits.h>
#include<string.h>
#define MAX 4
int lookup[MAX][MAX];
int MatrixChainOrder(int p[], int i, int j)
{
if(i==j) return 0;
int min = INT_MAX;
int k, count;
if(lookup[i][j]==0){
// recursively calculate count of multiplcations and return the minimum count
for (k = i; k<j; k++) {
int gmin=0;
if(lookup[i][k]==0)
lookup[i][k]=MatrixChainOrder(p, i, k);
if(lookup[k+1][j]==0)
lookup[k+1][j]=MatrixChainOrder(p, k+1, j);
count = lookup[i][k] + lookup[k+1][j] + p[i-1]*p[k]*p[j];
if (count < min){
min = count;
printf("\n****%d ",k); // i think something has be done here to represent the correct answer ((AB)C)D where first mat is represented by A second by B and so on.
}
}
lookup[i][j] = min;
}
return lookup[i][j];
}
// Driver program to test above function
int main()
{
int arr[] = {2,3,6,4,5};
int n = sizeof(arr)/sizeof(arr[0]);
memset(lookup, 0, sizeof(lookup));
int width =10;
printf("Minimum number of multiplications is %d ", MatrixChainOrder(arr, 1, n-1));
printf("\n ---->");
for(int l=0;l<MAX;++l)
printf(" %*d ",width,l);
printf("\n");
for(int z=0;z<MAX;z++){
printf("\n %d--->",z);
for(int x=0;x<MAX;x++)
printf(" %*d ",width,lookup[z][x]);
}
return 0;
}
我知道使用制表方法打印解决方案很容易,但我想在记忆技术中做到这一点。
谢谢。
【问题讨论】:
标签: algorithm matrix dynamic-programming memoization