zoukankan      html  css  js  c++  java
  • 最佳加法表达式(动态规划)

    点击打开链接


    描述

    给定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 都装不下的大整数,并用模拟列竖式的办法进行大整数的加法。
    来源
    Guo Wei[cpp] view plain co

    [cpp] view plain copy
    1. #include<bits/stdc++.h>  
    2. #include<cstring>  
    3. #include<stdlib.h>  
    4. using namespace std;  
    5. const int MaxLen = 55;  
    6. const string maxv = "999999999999999999999999999999999999999999999999999999999";  
    7. string ret[MaxLen][MaxLen];  
    8. string num[MaxLen][MaxLen];  
    9. int cmp(string &num1,string &num2)  
    10. {  
    11.     int l1 = num1.length();  
    12.     int l2 = num2.length();  
    13.     if (l1 != l2)  
    14.     {  
    15.         return l1-l2;  
    16.     }  
    17.     else  
    18.     {  
    19.         for (int i=l1-1; i>=0; i--)  
    20.         {  
    21.             if (num1[i]!=num2[i])  
    22.             {  
    23.                 return num1[i]-num2[i];  
    24.             }  
    25.         }  
    26.         return 0;  
    27.     }  
    28. }  
    29. void add (string &num1,string &num2,string &num3)  
    30. {  
    31.     //加法从低位到高位相加,那么需要将字符串倒过来  
    32.     int l1 = num1.length();  
    33.     int l2 = num2.length();  
    34.     int maxl = MaxLen,c = 0;        //c是进位标志  
    35.     for (int i=0; i<maxl; i++)  
    36.     {  
    37.         int t;  
    38.         if (i < l1 && i < l2)  
    39.         {  
    40.             t = num1[i]+num2[i]-2*'0'+c;  
    41.         }  
    42.         else if (i < l1 && i >= l2)  
    43.         {  
    44.             t = num1[i] - '0' + c;  
    45.         }  
    46.         else if (i >= l1 && i < l2)  
    47.         {  
    48.             t = num2[i] - '0' + c;  
    49.         }  
    50.         else  
    51.         {  
    52.             break;  
    53.         }  
    54.         num3.append(1,t%10+'0');  
    55.         c = t/10;  
    56.     }  
    57.     while (c)  
    58.     {  
    59.         num3.append(1,c%10+'0');  
    60.         c /= 10;  
    61.     }  
    62. }  
    63. int main()  
    64. {  
    65.     int m;                  //加号数目  
    66.     string str;             //输入的字符串  
    67.     while(cin >> m >> str)  
    68.     {  
    69.         //为了之后的加法计算先将这个字符串倒过来  
    70.         reverse(str.begin(),str.end());  
    71.         int n = str.length();  
    72.         for (int i=0; i<n; i++)  
    73.         {  
    74.             num[i+1][i+1] = str.substr(i,1);  
    75.         }  
    76.         for (int i=1; i<=n; i++) //求解对应的num[i][j]  
    77.         {  
    78.             for (int j=i+1; j<=n; j++)  
    79.             {  
    80.                 num[i][j] = str.substr(i-1,j-i+1);  
    81.             }  
    82.         }  
    83.         //当加号数目为0  
    84.         for (int i=1; i<=n; i++)  
    85.         {  
    86.             ret[0][i] = num[1][i];  
    87.         }  
    88.         for (int i=1; i<=m; i++) //对于加号数目的枚举  
    89.         {  
    90.             for (int j=1; j<=n; j++) //对于长度的枚举  
    91.             {  
    92.                 string minv = maxv;  
    93.                 string tmp;  
    94.                 for (int k=i; k<=j-1; k++)  
    95.                 {  
    96.                     tmp.clear();  
    97.                     add(ret[i-1][k],num[k+1][j],tmp);  
    98.                     if (cmp(minv,tmp)>0)  
    99.                     {  
    100.                         minv = tmp;  
    101.                     }  
    102.                 }  
    103.                 ret[i][j] = minv;  
    104.             }  
    105.         }  
    106.         //将原先颠倒的字符串倒回来  
    107.         reverse(ret[m][n].begin(),ret[m][n].end());  
    108.         cout << ret[m][n] << endl;  
    109.     }  
    110.     return 0;  
    111. }  



    这道题真的不会,就找了被人的代码贴上了,方便以后查看





















    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    关于sizeof表达式作为数组元素个数的编译
    【deque】滑动窗口、双端队列解决数组问题
    【二叉树】重建二叉树
    字符数组与字符串指针
    【STL】C中的qsort与C++中的sort
    对C++不是类型安全语言的理解
    【vector】创建一个二维vector当作二维数组用
    批量处理改变文件名、文件后缀名
    位运算
    关于sqlserver帐号被禁用问题
  • 原文地址:https://www.cnblogs.com/h-hkai/p/7406488.html
Copyright © 2011-2022 走看看