动态规划问题

优化矩阵连乘顺序以减少计算量

   矩阵相乘问题:

完全加括号的矩阵连乘积可递归地定义为:

     (1)单个矩阵是完全加括号的;

     (2)矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)

       例如,矩阵连乘积A1A2A3A4有5种不同的完全加括号的方式:(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)。每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。

      看下面一个例子,计算三个矩阵连乘{A1,A2,A3};维数分别为10*100 , 100*5 , 5*50 按此顺序计算需要的次数((A1*A2)*A3):10X100X5+10X5X50=7500次,按此顺序计算需要的次数(A1*(A2*A3)):10*5*50+10*100*50=75000次

      所以问题是:如何确定运算顺序,可以使计算量达到最小化。    

   
 int p[L]={30,35,15,5,10,20,25};
记录上面的a1,a2,a3....的值
 //p用来记录矩阵的行列,main函数中有说明
 5 //m[i][j]用来记录第i个矩阵至第j个矩阵的最优解
 6 //s[][]用来记录从哪里断开的才可得到该最优解
 7 int p[MAX+1],m[MAX][MAX],s[MAX][MAX];
 8 int n;//矩阵个数
 9 
10 void matrixChain(){
11     for(int i=1;i<=n;i++)m[i][i]=0;
12 
13     for(int r=2;r<=n;r++)//对角线循环,在这里面用来控制M[i:j]的长度

14         for(int i=1;i<=n-r+1;i++){//行循环
15             int j = r+i-1;//列的控制,是链的最后一个长度值

16             //找m[i][j]的最小值,先初始化一下,令k=i
17             m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];
18             s[i][j]=i;
19             //k从i+1到j-1循环找m[i][j]的最小值
20             for(int k = i+1;k<j;k++){
21                 int temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
22                 if(temp<m[i][j]){
23                     m[i][j]=temp;
24                     //s[][]用来记录在子序列i-j段中,在k位置处
25                     //断开能得到最优解
26                     s[i][j]=k;
27                 }
28             }
29         }
30 }
31 
举例:

当R=2时,先迭代计算出:

     m[1:2]=m[1:1]+m[2:2}+p[0]*p[1]*p[2];

     m[2:3]=m[2:2]+m[3:3]+p[1]*p[2]*p[3];

     m[3:4]=m[3:3]+m[4][4]+p[2]*p[3]*p[4];

     m[4:5]=m[4:4]+m[5][5]+p[3]*p[4]*p[5];

     m[5:6]=m[5][5]+m[6][6]+p[4]*p[5]*p[6]的值;

     当R=3时,迭代计算出:

     m[1:3]=min(m[1:1]+m[2:3]+p[0]*p[1]*p[3],m[1:2]+m[3:3]+p[0]*p[2]*p[3]);

     m[2:4]=min(m[2:2]+m[3:4]+p[1]*p[2]*p[4],m[2:3]+m[4:4]+p[1]*p[3]*p[4]);

     ......

     m[4:6]=min(m[4:4]+m[5:6]+p[3]*p[4]*p[6],m[4:5]+m[6:6]+p[3]*p[5]*p[6]);

     ......

例如,在计算m[2][5]时,依递归式有

    所以m[2][5] = 7125,且k=3,因此,s[2][5]=3。

通过这些可以得到一个最优值:

但是怎么通过s[i][j]的到最优值呢

参考:http://blog.youkuaiyun.com/liufeng_king/article/details/8497607
参考:http://www.cnblogs.com/liushang0419/archive/2011/04/27/2030970.html
1.问题描述 给定一个N*N 的方形网格,设其左上角为起点,坐标为(1,1),X 轴向右为正,Y 轴 向下为正,每个方格边长为1。一辆汽车从起点出发驶向右下角终点,其坐标为(N,N)。 在若干个网格交叉点处,设置了油库,可供汽车在行驶途中油。汽车在行驶过程中应遵守 如下规则: (1)汽车只能沿网格边行驶,装满油后能行驶K 条网格边。出发时汽车已装满油,在 起点与终点处不设油库。 (2)当汽车行驶经过一条网格边时,若其X 坐标或Y 坐标减小,则应付费用B,否则 免付费用。 (3)汽车在行驶过程中遇油库则应满油并付油费用A。 (4)在需要时可在网格点处增设油库,并付增设油库费用C(不含油费用A)。 (5)(1)~(4)中的各数N、K、A、B、C均为正整数。 算法设计: 求汽车从起点出发到达终点的一条所付费用最少的行驶路线。 数据输入: 输入数据。第一行是N,K,A,B,C的值,2 <= N <= 100, 2 <= K <= 10。第二行起是一个N*N 的0-1方阵,每行N 个值,至N+1行结束。方阵的第i 行第j 列处的值为1 表示在网格交叉点(i,j)处设置了一个油库,为0 时表示未设油库。 各行相邻的2 个数以空格分隔。 结果输出: 将找到的最优行驶路线所需的费用,即最小费用输出. Sample input 9 3 2 3 6 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 Sample output 12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值