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
Sample Output
题意: 现在给出你每个矩阵的围数, 要求你计算出用最少的乘法次数计算出矩阵链乘结果.
例如: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;
}
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;
}
相关文章推荐
- 深度优先搜索(deep first search)
- ACM: 简单排序题 poj 2231 动动脑…
- 动态规划: 装配线调度问题 (算法导…
- cordova加载层、进度条、文件选择插件
- Jmeter(7)调试工具---HTTP Mirror Server
- HDU_3308_线段树_区间合并
- ACM: 几何题+hash题 poj 2002
- 数论:复合数模的任意次同余式
- ACM: 简单题 poj 1152 (简单题也wr…
- ACM: 二进制问题 数论题 poj 1023
- 数论: 一次同余式 (中国剩余定律)
- ACM: 树的直径(两点最长距离) 图论…
- 柴俊理金:5、19午夜黄金,宁贵沥青操作策略
- ACM: 直接敲出LCA算法 图论题 poj …
- ACM: 最近公共祖先问题LCA 图论题 …
- 几天了,终于把Xshell连上了
- ACM: 最近公共祖先tarjan poj 1986
- 基于bootstrap 的确认框
- ACM: 概率DP 动态规划题 poj 1322
- ACM: 数学规律题 数论题 hdoj 1021