ACM PKU 1651 Multiplication Puzzle http://acm.pku.edu.cn/JudgeOnline/problem?id=1651
这是一个很经典的DP问题--矩阵连乘问题;
题目大意是给定n个数,移除每个数的代价是其与左右两数的乘积,求移除剩两个数的需要花费的最小代价。
我对题目进行解读主要是帮助那些对矩阵连乘问题不太熟悉了兄弟们,希望通过本菜鸟的解说,能帮助你们加速理解核心代码意思!
状态转换方程:sign[i][j] = min{sign[i][k]+sign[k][j]+num[i]*num[k]*num[j];其中i<k<j};
下面我对我的code作注(加粗字为核心代码):
题目大意是给定n个数,移除每个数的代价是其与左右两数的乘积,求移除剩两个数的需要花费的最小代价。
我对题目进行解读主要是帮助那些对矩阵连乘问题不太熟悉了兄弟们,希望通过本菜鸟的解说,能帮助你们加速理解核心代码意思!
状态转换方程:sign[i][j] = min{sign[i][k]+sign[k][j]+num[i]*num[k]*num[j];其中i<k<j};
下面我对我的code作注(加粗字为核心代码):
#include <iostream> using namespace std; const int MAX = 101; int num[MAX]; int sign[MAX][MAX]; int main () { int n; while (scanf("%d",&n)!=EOF) { memset(num,0,sizeof (num)); //初始化两个数组; memset(sign,0,sizeof(sign)); int i = 1, r = 0,j = 0,k = 0; while (i <= n) { scanf ("%d",&num[i]); i++; } for ( r = 2 ;r < n; r++) //外层循环控制i ;j之间的距离; for (i = 1; i <= n-r; i++) //内层循环遍历范围内的每一个值; { j = i + r ; if (r == 2) sign[i][j] = num[i]*num[i+1]*num[j]; //对相邻三个数求积; else { for (k =i + 1; k < j; k++) //探索每一个i,j之间的值,通过循环求出i,j之间满足题目要求的最小值; { if (sign[i][j] == 0) sign[i][j] =sign[i][k] + sign[k][j] + num[i]*num[k]*num[j]; else if (sign[i][k] + sign[k][j] + num[i]*num[k]*num[j] < sign[i][j]) sign[i][j] = sign[i][k] + sign[k][j] + num[i]*num[k]*num[j]; } //体现了状态转换方程的思路,通过记录数组和递归思想可以很快求出sign[1][n]的最小值; } } cout << sign[1][n] <<endl; } return 0; }