最优矩阵链乘

主要大区间化为小区间……

先小区间求值……

状态转移方程 f(i,j) = min{ f(i,k) + f(k+1,j) + p[i-1]p[k]p[j] };

poj 1651 http://poj.org/problem?id=1651

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>

const int MAXN = 100 + 10;
const double ESP = 10e-8;
const double Pi = atan(1.0) * 4;
const int INF = 0xfffffff;
const int MOD = 10000007;

using namespace std;

int n;
int dp[MAXN][MAXN];
int c[MAXN];

void multiplication(){
    for(int i = 0;i < n;i++){
        dp[i][i] = 0;
    }
    for(int l = 2;l < n;l++){
        for(int i = 1;i < n-l+1;i++){
            int j = i+l-1;
            dp[i][j] = INF;
            for(int k = i;k < j;k++){
                int tmp = dp[i][k] + dp[k+1][j] + c[i-1] * c[k] * c[j];
                dp[i][j] = min(dp[i][j],tmp);
            }
        }
    }
}
int main(){
    //freopen("input.txt","r",stdin);
    scanf("%d",&n);
    for(int i = 0;i < n;i++){
        scanf("%d",&c[i]);
    }
    multiplication();
    printf("%d\n",dp[1][n-1]);
    return 0;
}

poj 1179  http://poj.org/problem?id=1179

大致题意:

给你一个环,点是数字,边是运算,你断掉其中一条边之后,然后可以把相连的两个点经边的运算合并成一个点,求最大值

解题思路,枚举断的点然后进行矩阵相乘。

题解……1 我抄都抄不会的代码…… 抄来代码就是运行不对…… Orz ……http://m.blog.csdn.net/blog/u012962816/26822959

题解……2 http://www.tuicool.com/articles/Jj2Avi

在第一个自己笨到抄不对的时候,参考了题解2

然后从新自己写了一下……

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>

const int MAXN = 100 + 10;
const double ESP = 10e-8;
const double Pi = atan(1.0) * 4;
const int INF = 0xffffff;
const int MOD = 10000007;

using namespace std;
char edge[MAXN];
int vet[MAXN];
int dp1[MAXN/2][MAXN/2],dp2[MAXN/2][MAXN/2];
int fin[MAXN];
int N;
int main(){
   // freopen("input.txt","r",stdin);
    int ans = -INF;
    scanf("%d",&N);
    for(int i = 0;i < N;i++){
        getchar();
        scanf("%c %d",&edge[i],&vet[i]);
    }
    for(int t = 0;t < N;t++){ //从t位置为起点
        for(int i = 0;i < N;i++){  //进行矩阵的初始化
            dp1[i][i] = vet[(t+i)%N];
            dp2[i][i] = dp1[i][i];
        }
        for(int l = 2;l <= N;l++){     //j-i的长度
            for(int i = 0;i < N-l+1;i++){
                int maxv = -INF;
                int minv = INF;
                int j = i+l-1;
                for(int k = i;k < j;k++){
                    if(edge[(k+1+t)%N] == ‘t‘){   //这里也要相应的改变
                        maxv = max(maxv,dp1[i][k] + dp1[(k+1)%N][j]);
                        minv = min(minv,dp2[i][k] + dp2[(k+1)%N][j]);
                    }
                    else{
                        maxv = max(maxv,dp1[i][k] * dp1[(k+1)%N][j]);
                        maxv = max(maxv,dp2[i][k] * dp2[(k+1)%N][j]); //负负得正
                        minv = min(minv,dp1[i][k] * dp2[(k+1)%N][j]); //正负相乘
                        minv = min(minv,dp2[i][k] * dp2[(k+1)%N][j]);
                        minv = min(minv,dp2[i][k] * dp1[(k+1)%N][j]);  //正负相乘
                    }
                }
                dp1[i][j] = maxv;  //进行赋值
                dp2[i][j] = minv;
            }
        }
        ans = max(ans,dp1[0][N-1]);
        fin[t] = dp1[0][N-1];
    }
    printf("%d\n",ans);
    for(int i = 0;i < N;i++){
        if(fin[i] == ans){
            printf("%d ",i+1);
        }
    }
    printf("\n");
    return 0;
}

uva 10003 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=847&problem=944&mosmsg=Submission+received+with+ID+15274403

d(i,j)为 i - j 的最优费用,则 d(i,j) - min{ d(i,k) + d(k,j)  + a[j] - a[i] };

先小区间求值……

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>

const int MAXN = 1000 + 10;
const double ESP = 10e-8;
const double Pi = atan(1.0) * 4;
const int INF = 0xffffff;
const int MOD = 10000007;

using namespace std;
int a[MAXN];
int dp[MAXN][MAXN];
int main(){
   // freopen("input.txt","r",stdin);
    int len;
    while(~scanf("%d",&len) && len){
        int n;
        scanf("%d",&n);
        for(int i = 1;i <= n;i++){
            scanf("%d",&a[i]);
        }
        memset(dp,0,sizeof(dp));
        a[0] = 0;
        a[n+1] = len;
        for(int l = 2;l <= n+1;l++){
            for(int i = 0;i+l <= n+1;i++){
                int j = i+l;
                dp[i][j] = INF;
                for(int k = i+1;k < j;k++){
                    int tmp = dp[i][k] + dp[k][j] + a[j]-a[i];
                    if(tmp < dp[i][j]){
                        dp[i][j] = tmp;
                    }
                }
            }
        }
        printf("The minimum cutting is %d.\n",dp[0][n+1]);
    }
    return 0;
}
时间: 2024-08-15 05:04:07

最优矩阵链乘的相关文章

POJ1651:Multiplication Puzzle(区间DP 最优矩阵链乘)

题意:除了头尾不能动,每次取出一个数字,这个数字与左右相邻数字的乘积为其价值,最后将所有价值加起来,要求最小值 和最优矩阵链乘模型一样,最后取出的数决定了序,如果没学过最优矩阵连乘找重复子问题还是比较难找的 DP //180K 0MS #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int dp[110][110];

uva348 最优矩阵链乘 经典区间dp

// uva348 最优矩阵链乘 // 典型的区间dp // dp[i][j] 表示矩阵i到j链乘所得到的最小花费 // dp[i][j] = min(dp[i][k]+dp[k+1][j]+a[i].pl*a[k].pr*a[j].pr); // 在区间i到j上找一个k使得dp[i][k]+dp[k+1][j]这两部分的和在加上最后的 // a[i].pl*a[k].pr*p[i].pr的最小值; // 能有这样的状态关键是; P =A[1] * A[2] * .... * A[K] // 和

uva348Optimal Array Multiplication Sequence (最优矩阵链乘+路径输出)

Optimal Array Multiplication Sequence Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Practice UVA 348 Appoint description: Description Download as PDF Given two arrays A and B, we can determine the array C = AB using the

dp-最优矩阵链乘

来自于紫书 题目大意 有\(n\)个矩阵组成的序列,设计一种运算顺序把它们依次乘起来,使得总运算量最小.假设第i个矩阵\(A_i\)是\(P_{i-1} \times P_i\)的.(\(n<=100\)) 例如:假设\(A\).\(B\).\(C\)分别是\(1 \times 50 , 50 \times 20 , 20 \times 5\) \(A \times (B \times C)\)的运算量为\(1 \times 50 \times 5 + (50 \times 20 \times

UVA 348 Optimal Array Multiplication Sequence(最优矩阵链乘)

L - Optimal Array Multiplication Sequence Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 348 Appoint description:  acmparand  (2013-08-02)System Crawler  (2015-08-04) Description Given two arrays A a

矩阵链相乘问题

问题描述 给定n个矩阵A1,A2 ,...,An,相邻的矩阵是可乘的,如何确定一个最优计算次序,使得以此次序计算需要的数乘次数最少? 计算次序对计算性能的影响: 假设n=3,A1,A2,A3的维数分别为10×100,100×5,5×50.考察A1×A2×A3需要的数乘次数,有以下 两种计算方式: (1)(A1×A2)×A3:10×100×5+10×5×50=7500 (2) A1×(A2×A3):100×5×50+10×100×50=75000 通过这个简单的例子足以说明,矩阵的计算次序对计算性

算法13---动态规划矩阵链乘法

算法13---动态规划矩阵链乘法 矩阵链乘法是动态规划里面使用到的一个例子 1 两个矩阵的计算 那么对于一个矩阵的乘法,首先如果是两个矩阵的乘法,那么如何实现呢? 注意到我们使用二维数组表示矩阵,但是二维数组不能作为函数的返回值.具体实现如下 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <math.h> 4 5 #define a_rows 3 6 #define a_columns 4 7 #define

动态规划-矩阵链乘法

问题描述: 给定由n个要相乘的矩阵构成的序列(链)<A1,A2,...,An>,要计算乘积A1A2...An,可以将两个矩阵相乘的标准算法作为一个子程序,通过加括号确定计算的顺序(对同一矩阵链,不同的计算顺序所需要的计算次数大不相同). 目标问题:给定n个矩阵构成的矩阵链<A1,A2,...,An>,其中,i=1,2,...,n,矩阵Ai的维数为pi-1×pi,对乘积A1A2...An以一种最小计算次数加全部括号. 穷尽搜索: 令P(n)表示一串n个矩阵可能的加全部方案数.当n=1

Algorithm --&gt; 矩阵链乘法

动态规划--矩阵链乘法 1.矩阵乘法 Note:只有当矩阵A的列数与矩阵B的行数相等时A×B才有意义.一个m×r的矩阵A左乘一个r×n的矩阵B,会得到一个m×n的矩阵C. #include <iostream> using namespace std; #define A_ROWS 3 #define A_COLUMNS 2 #define B_ROWS 2 #define B_COLUMNS 3 void matrix_multiply(int A[A_ROWS][A_COLUMNS],in