动态规划——最大乘积

来源:互联网 发布:jy外设淘宝店网址 编辑:程序博客网 时间:2024/04/28 10:03

问题描述:

设有一个长度为N 的数字串,要求选手使用K 个乘号将它分成K+1 个部分,找出一种分法,使得这K+1 个部分的乘积最大。

同时,为了帮助选手能够理解题意,主持人还举了如下一个例子:

有一个数字串:312 ,当N=3K=1 时会有两种分法:

3*12=36

31*2=62

这时,符合题目要求的结果是:31*2=62 。现在,请你帮助你的好朋友XZ 设计一个程序,求得正确的答案。

输入

程序的输入共有两行:

第一行共有2 个自然数NK2N401K6

第二行是一个长度为N 的数字串。

输出

结果显示在屏幕上,相对于输入,应输出所求得的最大乘积(一个自然数)。

样例输入

    4 2

    1231

样例输出

    62

问题分析:

由于自然数位数的上限为40 ,乘号数的上限为6 ,因此最大乘积位数的上限接近42 位。显然,运算任何整数类型都无法容纳如此之大的数据,这里介绍动态规划的解法。

动态规划求解

对于长度为n的字符序列。对于字符序列s1,s2,……,si,(0=<i<n),插入j个“*”后形成最大乘积,用c[i][j]表示。

假设第j个“*”的插入位置是sk(之后),那么可以证明,对于s1,s2,……,sk,(0<=k<i),插入j-1个“*”也形成一个最大乘积c[k][j-1]。

于是我们就找到了这个问题的最优子结构:

 

c[i][j]= max{0<=k<i}(c[k][j-1]*s(k+1)*s(k+2)*……*si),

 其中,要保证j>=0,并且j<=K && j<i+1(即对于元素(s0~s(i)),最多插入i个“*”)。

对于边界情况,即当j=0时,c[i][0]=s[s0,……,s(i-1)]表示的整数值,(0=<i<n)。

建立数组c[N][K+1],因为j可以达到K,所以第二维长度应该为K+1。

实现代码如下:
  1 #include <iostream>
  2 using namespace std;
  3
  4 #define N 4 //the len of array
  5 #define M 2 //the count of *
  6 int countArray(char *s,int start,int len)
  7 {
  8         long sum = 0;
  9         for(int i = 0;i<len;i++)
 10         {
 11                 sum = sum*10 + s[start+i]-48;
 12         }
 13         return sum;
 14 }
 15 void max_multipl(int c[][M+1],char *s)
 16 {
 17         int i = 0;
 18         int j = 0;
 19         for(i = 0;i<N;i++)
 20         {
 21                 c[i][0] = countArray(s,0,i+1);
 22                 cout << c[i][0]<< endl;
 23         }
 24         for(i = 0;i<N;i++)//数组元素从0开始
 25         {
 26                 for(j = 1;j< i+1 && j<= M;j++)
 27                 {
 28                         c[i][j] = 0;
 29                         for(int k = 0;k<i;k++)
 30                         {
 31                                 long t;
 32                                 t = c[k][j-1] * countArray(s,k+1,i-k);
 33                                 cout <<"***************" << endl;
 34                                 cout << c[k][j-1] << "  " <<t << endl;
 35                                 if(t>c[i][j])
 36                                         c[i][j] = t;
 37                                 cout << "c["<<i<<"]"<<"["<<j<<"] = "<<c[i][j]<<endl;
 38                                 cout <<"***************" << endl;

 39                         }
 40                 }
 41
 42         }
 43         //cout << c[N-1][M];
 44 }
 45 int main()
 46 {
 47         char s[N] = {'1','2','3','5'};
 48         int c[N][M+1]={0};
 49         max_multipl(c,s);
 50 }

原创粉丝点击