• 区间DP——整数划分


    D. 整数划分

    内存限制:128 MiB    时间限制:1000 ms    标准输入输出
    题目类型:传统      评测方式:文本比较

    题目描述

    如何把一个正整数N(N长度<20)划分为M(M>1)个部分,使这M个部分的乘积最大。N、M从键盘输入,输出最大值及一种划分方式。

    输入格式

    第一行一个正整数T(T<=10000),表示有T组数据

    接下来T行每行两个正整数N,M。

    输出格式

    对于每组数据

    第一行输出最大值。

    第二行输出划分方案,将N按顺序分成M个数输出,两个数之间用空格格开。

    样例

    样例输入

    1

    199 2

    样例输出

    171

    19 9

    思路:设dp[i][j]表示前i位分成j段,则有i>=j!(段数小于等于个数)

    设A[i][j]表示第i位到j位(包括i,j)中间的数(进行预处理)

     

    dp[i][j]=dp[k-1][j-1]*A[k][i];
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<stack>
     5 using namespace std;
     6 unsigned long long A[21][21],dp[21][21],maxi,son[21][21],key,ink;
     7 char in[22];
     8 stack <int> out;
     9 inline void clean()
    10 {
    11     memset(dp,0,sizeof(dp));
    12     memset(son,0,sizeof(son));
    13     memset(in,0,sizeof(in));
    14     memset(A,0,sizeof(A));
    15     key=0;
    16 }
    17 void goback (int n,int m)
    18 {
    19     if(!m)return ;
    20     goback(son[n][m],m-1);
    21     for (int i=son[n][m]+1;i<=n;i++)
    22       cout<<in[i];
    23     cout<<" ";
    24     return ;
    25 }
    26 int nzu,n,m;
    27 int main()
    28 {
    29     //freopen("1.in","r",stdin);
    30     //1freopen("6661.out","w",stdout);
    31     cin>>nzu;
    32     for(int wai=1;wai<=nzu;wai++)
    33     {
    34         clean();
    35         cin>>in+1;
    36         n=strlen(in+1);
    37         cin>>m;
    38         for(int i=1;i<=n;i++)
    39         {
    40             ink=0;
    41             for(int j=i;j<=n;j++)
    42             {
    43                 ink=ink*10+in[j]-'0';
    44                 A[i][j]=ink;
    45             }
    46         }
    47         dp[0][0]=1;
    48         for(int i=1;i<=n;i++)/*dp[i][j]-->前i位分成j段*/
    49         {
    50             int ki=min(i,m);
    51             for(int j=1;j<=ki;j++)
    52             {
    53                 for(int k=1;k<=i;k++)
    54                 {
    55                     if(dp[k-1][j-1]*A[k][i]>dp[i][j])
    56                     {
    57                         dp[i][j]=dp[k-1][j-1]*A[k][i];
    58                         son[i][j]=k-1;
    59                     }
    60                 }
    61             }
    62         }
    63         cout<<dp[n][m]<<endl;
    64         if(m==n)
    65         {
    66             for(int i=1;i<=n;i++)
    67                 cout<<in[i]<<" "; 
    68         }
    69         else goback(n,m);
    70         cout<<endl;        
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    Android消息推送完美方案[转]
    这一路走来
    【深入比较ThreadLocal模式与synchronized关键字】
    前端闭包 解决异步执行问题
    微信小程序在wxml双大括号中执行复杂运算
    腾讯云对象存储使用
    CSS中的flex布局
    docker基础学习笔记
    redis学习笔记
    微信小程序页面栈管理
  • 原文地址:https://www.cnblogs.com/lihaolin/p/11274350.html
Copyright © 2020-2023  润新知