整数划分 区间dp

怼烎@ 2022-08-20 15:15 381阅读 0赞

题目链接点击打开链接

题目大意是说有一个不超过二十位的数字,要将这个数字划分成n段,最后让这n段数字相乘,问怎么划分使乘积最大。

分析:

一个很经典的区间dp问题,我们可以先保存下这个数字的每段的大小,也就是a[i][j]表示的这个数字的i位到j位的大小。

然后就是一个很普通的区间dp了,dp[i][j]表示的是前i位里面插入j个乘号所得到的最大值。

我们知道最后的乘积肯定比原来的那个数字小,所以没有超过long long的范围。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. using namespace std;
  7. int const maxn = 21 ;
  8. long long dp[maxn][maxn];
  9. long long Arr[maxn][maxn];
  10. int main()
  11. {
  12. int t,m ;
  13. string n;
  14. scanf("%d",&t);
  15. while(t--)
  16. {
  17. memset(dp,0,sizeof(dp));
  18. cin>>n>>m;
  19. m--;///m-1个乘号
  20. int len=n.length();
  21. for(int i=0;i<len;i++)
  22. {
  23. Arr[i][i]=n[i]-'0';
  24. for(int j=i+1;j<len;j++)
  25. {
  26. Arr[i][j]=Arr[i][j-1]*10+n[j]-'0';
  27. }
  28. }
  29. for(int i=0;i<len;i++)
  30. {
  31. dp[i][0]=Arr[0][i];
  32. }
  33. for(int j=1;j<=m;j++) //j为*数目
  34. {
  35. for(int i=j;i<len;i++)//i为数字位置(肯定要从j开始,要包含*处理完)
  36. {
  37. for(int k=j-1;k<i;k++)//枚举区间
  38. {
  39. dp[i][j]=max(dp[i][j],dp[k][j-1]*Arr[k+1][i]);
  40. }
  41. }
  42. }
  43. printf("%lld\n",dp[len-1][m]);
  44. }
  45. return 0;
  46. }

发表评论

表情:
评论列表 (有 0 条评论,381人围观)

还没有评论,来说两句吧...

相关阅读

    相关 整数划分 区间dp

    题目链接[点击打开链接][Link 1] 题目大意是说有一个不超过二十位的数字,要将这个数字划分成n段,最后让这n段数字相乘,问怎么划分使乘积最大。 分析: 一

    相关 整数划分--DP

    5. [数的划分][Link 1] 问题描述   将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。   例如:n=7,k=3,下面三种分法被认为是相同

    相关 整数划分 dp

    蒜头君特别喜欢数学。今天,蒜头君突发奇想:如果想要把一个正整数 nn 分解成不多于 kk 个正整数相加的形式,那么一共有多少种分解的方式呢? 蒜头君觉得这个问题实在是太难了,

    相关 区间dp

    让我求解在一个区间上的最优解,那么我把这个区间分割成一个个小区间,求解每个小区间的最优解,再合并小区间得到大区间即可。所以在代码实现上,我可以枚举区间长度len为每次分割成的小