码迷,mamicode.com
首页 > 编程语言 > 详细

dp算法第三发之noip乘积最大

时间:2017-10-07 17:46:03      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:描述   ring   int   style   方式   数字串   font   根据   string   

乘积最大(2000noip)

【题目描述】

今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活 动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样 一道题目: 
设有一个长度N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。 
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子: 
有一个数字串: 312,当N=3,K=1时会有以下两种分法: 
1)3*12=36 
2)31*2=62 
这时,符合题目要求的结果是: 31*2=62 
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

【输入】

输入共有两行: 
第一行共有2个自然数N,K (6<=N<=40,1<=K<=6) 
第二行是一个K度为N的数字串。
【输出】

所求得的最大乘积(一个自然数)。
【输入样例】

4 2
1231
【输出样例】

62

分析:

搞竞赛的人都应该做过这道题(显然是2000年的题嘛)。

题目给出两个关键数值N和K对不对?假设F(N,K)就是对字符串前N位插入K个乘号后所能得到的最大值,考虑一下F(N,K)与F(N-1,K)、F(N-1,K-1)的关系?如果你也是搞竞赛的,点到即止。算法题应该到算法版问,你在ASP.NET版问,大家平常都不是研究这个的,你能得到的答案可能就不是那么优化。

附例子:

312:当N=3,   K=1时,从N=1,   K=0开始推导 
F(1,   0)   =   3 
F(2,   0)   =   31 
F(3,   1)   =   max(F(1,   0)*12,   F(2,0)*2)   =   max(36,   62)   =   62

31245:N=5,   K=2,还是从F(1,   0)开始推导 
F(1,   0)   =   3 
F(2,   0)   =   31 
F(3,   0)   =   312 
F(2,   1)   =   3*1   =   3 
F(3,   1)   =   max(F(1,   0)   *   12,   F(2,   0)   *   2)   =   max(36,   62)   =   62 
F(4,   1)   =   max(F(1,   0)   *   124,   F(2,   0)   *   24,   F(3,   0)   *   4)   =   max(372,   744,   1248)   =   1248 
F(5,   2)   =   max(F(2,   1)   *   245,   F(3,   1)   *   45,   F(4,   1)   *   5)   =   max(735,   2790,   6240)   =   6240

因为题目仅需要求最后的值,不需要输出到底是如何插入乘号能得到这个最大值(通常竞赛题都这样),因此这样的计算方法获得最大值就足够了。如果你要追寻哪种插入方式得到了最大值,每次max时你都要把最大值的选择保存下来,最后根据这个选择确定原先进行了乘号插入的地方。

 

动态规划方程:     
设A[I,Num]       B[I,Num]       是第一个数字到第I个数字中加Num个乘号所得的最大值 ,s[k,I]表示从第k位到第I位的一个数字       
  那么       
 B[I,Num]=max(A[k,Num-1]*S[k+1,I])       1+Num-1 <=k <=I;      

 给出代码:

 

#include<iostream>

#include<string>

#include<cstring>

using namespace std;

const int M = 50;

 

struct Bigint{

         int data[M];

         Bigint(){

                  memset(data,0,sizeof(data));

                  data[0] = 1;

         }

         Bigint(int x){

                  memset(data,0,sizeof(data));

                  data[0] = 1;

                  if (x==0) return;

                  int i=0;

                  while (x){

                          data[++i] = x%10;

                          x /= 10;

                  }

                  data[0] = i;

         }

         Bigint(string s){                

                  memset(data,0,sizeof(data));

                  data[0] = s.size();

                  for (int i=1;i<=data[0];i++)

                          data[i] = s[data[0]-i]-‘0‘;

                  clear0();

         }      

         Bigint operator *(const Bigint &x) {

                  Bigint c;

                  c.data[0] = data[0]+x.data[0]-1;

                  for (int i=1;i<=data[0];i++)

                          for (int j=1;j<=x.data[0];j++)

                                   c.data[i+j-1] += data[i]*x.data[j];

                  for (int i=1;i<=c.data[0];i++)

                          c.data[i+1] += c.data[i]/10,

                           c.data[i] %= 10;

                  if (c.data[c.data[0]+1]) c.data[0]++;

                  c.clear0();

                  return c;

         }

         bool operator < (const Bigint &x)const{

                  if (data[0]!=x.data[0]) return data[0]<x.data[0];

                  for (int i=data[0];i>0;i--)

                          if (data[i]!=x.data[i])

                                   return data[i]<x.data[i];

                  return false;

         }

         void clear0(){

                  while (data[data[0]]==0 && data[0]>1) data[0]--;

         }

};

 

ostream& operator << (ostream& out, const Bigint &x){

         for (int i=x.data[0];i>0;i--)

                  out<<x.data[i];

         return out;

}

Bigint f[50][50],a[50][50];

 

int main(){

//     freopen("maxmu.in","r",stdin);

//     freopen("maxmu.out","w",stdout);

         int n,K;

         string s;

         cin>>n>>K>>s;

         for (int i=1;i<=n;i++)

                  for (int j=1;j<=n-i+1;j++)

                          a[i][j] = (Bigint)s.substr(i-1,j);//a[i][j]:从第i个数开始连续j个数形成的整数

         for (int i=1;i<=n;i++)

                  f[i][0] = a[1][i];

         Bigint t;

         for (int i=2;i<=n;i++) //f[i][j]:表示前i个数用j个乘号的最优解

                  for (int j=1;j<i && j<=K;j++)

                          for (int k=1;k<=i-j;k++){

                                   t = f[i-k][j-1]*a[i-k+1][k];

                                   if (f[i][j]<t) f[i][j] = t;

                          }

         cout<<f[n][K]<<endl;

         return 0;

}

dp算法第三发之noip乘积最大

标签:描述   ring   int   style   方式   数字串   font   根据   string   

原文地址:http://www.cnblogs.com/powerfulbee/p/7634934.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!