动态规划算法——乘法表问题

来源:互联网 发布:怎样用网络电视看直播 编辑:程序博客网 时间:2024/05/21 17:13

问题描述:

定义于字母表∑{a,b,c)上的乘法表如表1所示
表1∑乘法表
    a  b  c
a  b  b  a
b  c  b  a
c  a  c   c

依此乘法表,对任一定义于∑上的字符串,适当加括号表达式后得到一个表达式。例如,对于字符串x=bbbba,它的一个加括号表达式为i(b(bb))(ba)。依乘法表,该表达式的值为a。试设计一个动态规划算法,对任一定义于∑上的字符串x=x1x2…xn,计算有多少种不同的加括号方式,使由x导出的加括号表达式的值为a
要求:
     输入:输入一个以a,b,c组成的任意一个字符串。
     输出:计算出的加括号方式数。

算法实现:可以定义一个三维数组a[n][n][3],n为输入字符串的长度,a[i][j][0]为从字符串中第i个元素到第j个元素的子串表达式值为a的加括号方式数,a[i][j][1]为从字符串中第i个元素到第j个元素的子串表达式值为b的加括号方式数,a[i][j][2]为从字符串中第i个元素到第j个元素的子串表达式值为c的加括号方式数。

     由乘法表的定义则可知啊a[i][j][0]=(对k求和,k从i到j-1)a[i][k][0]*a[i][k+1][2]+a[i][k][1]*a[i][k+1][2]+a[i][k][2]*a[i][k+1][1];

     同理可得到a[i][j][1]和a[i][j][2]。

     同时由上面的表达式可知,要计算a[i][j][],需先计算a[i][k][]和a[i][k+1][],这里k从i到j-1,故a[i][j][]可采取如下的计算次序

如图所示,先将主对角线上从上到下计算出来,再计算次对角线,再次次对角线.....依次顺序,直到全部计算完毕。

 

下面给出c语言程序:

#include "stdio.h"

#define num 50
void chengji_1(int (*a)[num][3],int n,char b[]);

 

int _tmain( )
{
 int a[num][num][3];
 char b[num];
 int i,j,k,n;
 char c;
 printf("intput the num of array:");
 scanf("%d",&n);
 getchar();
 for(i=0;i<n;i++)
  for(j=0;j<n;j++)
   for(k=0;k<3;k++)
    a[i][j][k]=0;
 i=0;
 while((c=getchar())!='/n')
 {
  b[i]=c;
  i++;
 }
 chengji_1(a,n,b);
 printf("reslut is:%d",a[0][n-1][0]);
 getchar();
 
}

 

 

void chengji_1(int (*a)[num][3],int n,char b[])
{
 int i,j,k,t;
 for(i=0;i<n;i++)
  *(*(*(a+i)+i)+(b[i]-'a'))=1;
 for(k=1;k<n;k++)
  for(i=0;i<n;i++)
  {
   j=i+k;
   for(t=i;t<j;t++)
   {
    *(*(*(a+i)+j)+0)+=((*(*(*(a+i)+t)+0))*(*(*(*(a+t+1)+j)+2))+(*(*(*(a+i)+t)+1))*(*(*(*(a+t+1)+j)+2))+(*(*(*(a+i)+t)+2))*(*(*(*(a+t+1)+j)+0)));
    *(*(*(a+i)+j)+1)+=((*(*(*(a+i)+t)+0))*(*(*(*(a+t+1)+j)+0))+(*(*(*(a+i)+t)+0))*(*(*(*(a+t+1)+j)+1))+(*(*(*(a+i)+t)+1))*(*(*(*(a+t+1)+j)+1)));
    *(*(*(a+i)+j)+2)+=((*(*(*(a+i)+t)+1))*(*(*(*(a+t+1)+j)+0))+(*(*(*(a+i)+t)+2))*(*(*(*(a+t+1)+j)+1))+(*(*(*(a+i)+t)+2))*(*(*(*(a+t+1)+j)+2)));
   }
  }
 
}

运行结果如下: