標籤:blog http io ar for sp 2014 on log
題意:n個數(3 <= N <= 100)的序列,每次取一個數(不可以取最左最右)a[k],這時得到一個權值為a[k]左邊的數 * a[k] * a[k]右邊的數,問最小權值和。
題目連結:http://poj.org/problem?id=1651
——>>狀態:dp[i][j]表示第i個數到第j個數組成的序列的最小權值和。
狀態轉移方程:dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + a[i] * a[k] * a[j]);(枚舉最後一個拿掉的數來更新)
時間複雜度:O(n ^ 3)
#include <cstdio>#include <algorithm>#include <cstring>using std::min;const int MAXN = 100 + 1;int a[MAXN];int dp[MAXN][MAXN];void Read(int n){ for (int i = 1; i <= n; ++i) { scanf("%d", a + i); }}void Dp(int n){ memset(dp, 0x3f, sizeof(dp)); for (int i = 1; i < n; ++i) { dp[i][i + 1] = 0; } for (int nLen = 3; nLen <= n; ++nLen) { for (int i = 1; i <= n; ++i) { int j = i + nLen - 1; if (j > n) break; for (int k = i + 1; k < j; ++k) { dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + a[i] * a[k] * a[j]); } } }}void Output(int n){ printf("%d\n", dp[1][n]);}int main(){ int n; while (scanf("%d", &n) == 1) { Read(n); Dp(n); Output(n); } return 0;}
poj - 1651 - Multiplication Puzzle(dp)