POJ 1651:Multiplication Puzzle(区间DP)
http://poj.org/problem?id=1651
题意:给出n个数字,每取中间一个数,就会使得权值加上中间这个数和两边的乘积,求取剩两个数最少的权值是多少。
思路:区间dp。
一开始想了挺久还是写不出方程,做了点别的事回来再想就突然觉得很简单了。
一开始使得长度为1和2的区间dp[i][j]为0.
然后dp[i][j] = min(dp[i][k] + dp[k][j] + w[k] * w[i] * w[j])。
枚举的k为中间拿掉的数,然后和左右的区间和相加就是最后答案了。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define N 105 6 typedef long long LL; 7 LL dp[N][N], w[N]; 8 9 int main() { 10 int n; 11 while(~scanf("%d", &n)) { 12 memset(dp, 0x3f3f3f3f, sizeof(dp)); 13 for(int i = 1; i <= n; i++) scanf("%lld", &w[i]); 14 for(int i = 1; i <= n; i++) dp[i][i] = dp[i][i+1] = 0; 15 //for(int i = 2; i < n; i++) dp[i][i] = w[i-1] * w[i] * w[i+1]; 16 for(int len = 2; len < n; len++) { 17 for(int i = 1; i + len <= n; i++) { 18 int j = i + len; 19 for(int k = i + 1; k < j; k++) 20 dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + w[i] * w[j] * w[k]); 21 } 22 } 23 printf("%lld\n", dp[1][n]); 24 } 25 return 0; 26 }