• 百练4152:最佳加法表达式(dp+高精度)


    描述

    给定n个1到9的数字,要求在数字之间摆放m个加号(加号两边必须有数字),使得所得到的加法表达式的值最小,并输出该值。例如,在1234中摆放1个加号,最好的摆法就是12+34,和为36

    输入有不超过15组数据
    每组数据两行。第一行是整数m,表示有m个加号要放( 0<=m<=50)
    第二行是若干个数字。数字总数n不超过50,且 m <= n-1输出对每组数据,输出最小加法表达式的值样例输入

    2
    123456
    1
    123456
    4
    12345
    

    样例输出

    102
    579
    15
    

    提示要用到高精度计算,即用数组来存放long long 都装不下的大整数,并用模拟列竖式的办法进行大整数的加法。

    搞了半天的C++高精度,,结果还是可耻地用了java大数。。

     1 import java.math.BigDecimal;
     2 import java.math.BigInteger;
     3 import java.util.Scanner;
     4 
     5 public class Main {
     6     static BigInteger INF = new BigInteger("9999999999999999999999999999999999999999999999999999999");
     7     public static void main(String[] args) {
     8         // TODO Auto-generated method stub
     9         Scanner sc = new Scanner(System.in);
    10         BigInteger dp[][] = new BigInteger[55][55];
    11         int m,n;
    12         BigInteger s;
    13         
    14         while(sc.hasNext())
    15         {
    16             m = sc.nextInt();
    17             s = sc.nextBigInteger();
    18             
    19             n = s.toString().length();
    20             
    21             //BigDecimal num[][] = new BigDecimal[n+1][n+1];//num[i][j]表示从s第i个数到第j个数组成的数字
    22             /*
    23             for(int i = 1;i<=n;++i)
    24                 for(int j = 0;j<=n;++j)
    25                 {
    26                     if(i<=j)
    27                     {
    28                         num[i][j] = new BigDecimal(s.toString().substring(i-1,j));
    29                     }
    30                 }
    31                 */
    32             
    33             dp[0][0] = new BigInteger("0");//没有数字没有加号的最小值是0
    34             for(int i = 1;i<=n;++i)
    35             {
    36                 dp[i][0] =  new BigInteger(s.toString().substring(0,i));//没有加号的情况下,最小值就是数字自己
    37             }
    38             
    39             for(int i = 0;i<=n;++i)
    40                 for(int j = 1;j<=m;++j)
    41                 {
    42                     
    43                     dp[i][j] = INF;
    44                     if(i>=j+1)//j个加号能插入i个数字中
    45                     {
    46                         for(int k = j;k<i;++k)
    47                         {
    48                             dp[i][j] = dp[i][j].min(dp[k][j-1].add(new BigInteger(s.toString().substring(k,i))));
    49                         }
    50                     }
    51                 }
    52                 
    53             System.out.println(dp[n][m]);    
    54         }//while
    55     }
    56 
    57 }

     补一个师傅的C++做法,之后回来补

     1 #include <iostream>
     2 #include <algorithm>
     3 using namespace std;
     4 string Add(string &a, string &b) {
     5     string sum;
     6     int lena = a.length();
     7     int lenb = b.length();
     8     int i = 0;
     9     int j = 0;
    10     int carry = 0;
    11     int number = 0;
    12     while (i < lena || j < lenb) {
    13         number = carry;
    14         if (i < lena) number += (a[i++] - '0');
    15         if (j < lenb) number += (b[j++] - '0');
    16         sum += (number % 10 + '0');
    17         carry = number / 10;
    18     }
    19     if (carry == 1) {
    20         sum = sum + '1';
    21     }
    22 
    23     return sum;
    24 }
    25 
    26 //1大于 0等于 -1小于
    27 int comp(string &a, string &b) {
    28     if (a.length() > b.length()) return 1;
    29     if (a.length() < b.length()) return -1;
    30     for (int i = a.length() - 1; i >= 0; --i) {
    31         if (a[i] > b[i])
    32             return 1;
    33         else if (a[i] < b[i]) {
    34             return -1;
    35         }
    36     }
    37     return 0;
    38 }
    39 
    40 string maxSum(vector<vector<string>> &record, string& s, int start, int m) {
    41     if (m == 0) return s.substr(start);
    42 
    43     if (record[start][m] != "") {
    44         return record[start][m];
    45     }
    46 
    47     string &rec = record[start][m];
    48     string minNumber = s;
    49     for (int i = start; i < s.length() - m; ++i) {
    50         string sub = s.substr(start, i - start + 1);
    51         string remain = maxSum(record, s, i + 1, m - 1);
    52         string r = Add(sub, remain);
    53         if (comp(minNumber, r) == 1) {
    54             minNumber = r;
    55         }
    56     }
    57     return rec = minNumber;
    58 }
    59 
    60 int main()
    61 {
    62     int m;
    63     string s;
    64     while (cin >> m) {
    65         cin >> s;
    66         if (m == 0) {
    67             cout << s << endl;
    68             continue;
    69         }
    70         reverse(s.begin(), s.end());
    71         vector<vector<string>> record(s.length(), vector<string>(m + 1, ""));
    72         string sum = maxSum(record, s, 0, m);
    73         reverse(sum.begin(), sum.end());
    74         cout << sum << endl;
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    charles安装以及手机端的设置
    ON DUPLICATE KEY UPDATE 用法与说明
    亿级流量架构之网关设计思路、常见网关对比
    灰度发布系统架构设计
    Jmeter 并发测试
    springboot --- Swagger UI初识
    TortoiseGIT 一直提示输入密码的解决方法!
    MySQL 5.6 参数详解
    LVS 轮询调度详解
    MongoDB 权限
  • 原文地址:https://www.cnblogs.com/knmxx/p/9522598.html
Copyright © 2020-2023  润新知