您的位置:首页 > 其它

ACM: 矩阵链乘 动态规划题 poj 165…

2016-05-19 23:23 274 查看
Multiplication Puzzle

Description
The multiplication puzzle is
played with a row of cards, each containing a single positive
integer. During the move player takes one card out of the row and
scores the number of points equal to the product of the number on
the card taken and the numbers on the cards on the left and on the
right of it. It is not allowed to take out the first and the last
card in the row. After the final move, only two cards are left in
the row.

The goal is to take cards in such order as to minimize the total
number of scored points.

For example, if cards in the row contain numbers 10 1 50 20 5,
player might take a card with 1, then 20 and 50, scoring
10*1*50 + 50*20*5 + 10*50*5 = 500+5000+2500 = 8000

If he would take the cards in the opposite order, i.e. 50, then 20,
then 1, the score would be
1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150.

Input

The first line of the input
contains the number of cards N (3 <= N
<= 100). The second line contains N integers in the
range from 1 to 100, separated by spaces.
Output

Output must contain a single
integer - the minimal score.
Sample Input

6

10 1 50 50 20 5

Sample Output

3650


题意: 现在给出你每个矩阵的围数, 要求你计算出用最少的乘法次数计算出矩阵链乘结果.

     
例如:6个围数, 10*1,1*50,50*50,50*20,20*5这5个矩阵的链乘.

解题思路:

      
1. 我们知道矩阵链乘是满足结合率的, A1*A2*A3 = (A1*A2)*A3 = A1*(A2*A3);

      
2. 要确定最少的计算次数, 意味着我们要再矩阵链乘上面添加全括号.

      
问题分析:

           
当n = 1时, 一个矩阵形式:(A1)

           
当n >= 2时, 相当于(A1*A2*...Ak)*(Ak+1*...An)分成两部分.

      
3. 状态:dp[i][j]表示:从第i个矩阵到第j个矩阵的最少乘法次数.

      
4. 动态方程: dp[i][j] = dp[i][k]+dp[k+1][j] + p[i-1]*p[k]*p[j];

代码:

#include <cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 105

const int INF = (1<<30);

int n;

int dp[MAX][MAX], p[MAX];

 

inline int min(int a, int b)

{

 return a < b ? a : b;

}

 

int DP()

{

 for(int q = 2; q <= n; ++q)

 {

  for(int i = 1; i
<= n-q+1; ++i)

  {

   int j =
i+q-1;

   dp[i][j] =
INF;

   for(int k =
i; k <= j-1; ++k)

   {

    dp[i][j]
= min(dp[i][j], dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j]);

   }

  }

 }

 return dp[1]
;

}

 

int main()

{

// freopen("input.txt", "r", stdin);

 while(scanf("%d",&n) !=
EOF)

 {

  for(int i = 1; i
<= n; ++i)

  {

   scanf("%d",&p[i-1]);

   dp[i][i] =
0;

  }

 

  n = n-1;

  printf("%d\n", DP());

 }

 return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: