算法设计第三次上机作业-Multiplication Puzzle
题目描述
给出一排写有数字的卡片,每次都从这排卡片中抽取一张拿出(不能拿第一张和最后一张),将该卡片上的数字和其旁边的两个数字进行相乘,重复该过程直到最后只剩下第一张卡片和最后一张卡片。使得乘数相加得到的和最小。 例如,卡片上的数字为10 1 50 20 5, 如果抽取顺序为 1,20,50,那么最终得到的结果为 10x1x50 + 50x20x5 + 10x50x5 = 500+5000+2500 = 8000 如果抽取顺序为50,20,1,那么最终的结果为 1x50x20 + 1x20x5 + 10x1x5 = 1000+100+50 = 1150.
输入 第一行为N,代表共有N张卡片 第二行给出N个数字
输出 得到的最小的乘积和
解题思路
将该问题拆成小问题,那么最小的问题就是三个数字的情况。用一个二维数组d[i][j]来记录从i到j的最小乘积和,则该问题的最小子问题就是最后取走的元素是第k个元素,也就是d[i][j] = d[i][k] + d[k][j] + a[i]*a[j]*a[k] (i<k<j)
AC代码
#include <iostream>
#include <cstdio>
#include <cmath>
#define Max 105
const int INF
= 2147483647;
using namespace std
;
int d
[Max
][Max
];
int main(int argc
, const char * argv
[]) {
int N
;
int input
[Max
], d
[Max
][Max
];
cin
>>N
;
for(int i
=0; i
<N
; i
++) {
scanf("%d", &input
[i
]);
}
for(int i
=0; i
<N
; i
++) {
for(int j
=0; j
<N
; j
++) {
d
[i
][j
] = 0;
}
}
for(int k
=2; k
<N
; k
++) {
for(int i
=0; i
<N
-k
; i
++) {
int temp
, min_value
= INF
;
for(int m
=i
+1; m
<i
+k
; m
++) {
temp
= d
[i
][m
] + d
[m
][i
+k
] + input
[i
]*input
[m
]*input
[i
+k
];
if(temp
< min_value
) min_value
= temp
;
}
d
[i
][i
+k
] = min_value
;
}
}
cout
<<d
[0][N
-1]<<endl
;
return 0;
}
如果用递归的方法那么就是注释掉的那个函数,但是如果用递归的方法会TLE。所以动态规划就在于把每一步的结果都记录下来了,这样就可以避免每次用到这些数字的时候都计算一遍。