一看就知道是矩阵链,但是忘了矩阵链具体是怎么做的了,记的是把区间划分开来DP。
定义f[i, j]为 i-j 内的最小值(初始是1-n),如果第 k 个为最后选的数,那么 f[i, j] = f[i, k]+f[k,j]+a[i]*a[k]*a[j];
需要注意的是边界条件:如果区间内不含选取的数(i+1==j)最小值应该定义为0。
1 /* 2 POJ 1651 Multiplication Puzzle 3 */ 4 5 # include <cstdio> 6 # include <cstring> 7 8 # define N 100 + 5 9 # define INF 0x7FFFFFFF 10 11 int n; 12 int a[N]; 13 int f[N][N]; 14 15 int min(int x, int y) 16 { 17 return x<y ? x:y; 18 } 19 20 int dp(int l, int r) 21 { 22 int &ans = f[l][r]; 23 if (ans != -1) return ans; 24 if (l+1 == r) return ans = 0; 25 ans = INF; 26 for (int k = l+1; k < r; ++k) 27 ans = min(ans, dp(l, k)+dp(k,r)+a[k]*a[l]*a[r]); 28 return ans; 29 } 30 31 void solve(void) 32 { 33 for (int i = 1;i <= n; ++i) 34 { 35 scanf("%d", &a[i]); 36 memset(f[i]+1, -1, sizeof(int)*n); 37 } 38 int ans = dp(1, n); 39 printf("%d\n", ans); 40 } 41 42 int main() 43 { 44 while (~scanf("%d", &n)) 45 solve(); 46 47 return 0; 48 }
不知道算不算区间DP,就归为简单DP。
不知道怎么打印出字典序最小的路径(能不能每次选取满足乘积最小的下标最大的数?)。