4152:最佳加法表达式,考点:动态规划,高精度计算
作者:互联网
原题:http://bailian.openjudge.cn/practice/4152/
描述
给定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 都装不下的大整数,并用模拟列竖式的办法进行大整数的加法。
解法
大整数的加法:用一个类来实现
关键在于动规。
dp[m][n]表示在n个数字中插入m个加法所能形成
代码如下:(没有预处理Num(i,j),由于懒吧)
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 #define INF 1<<30 6 using namespace std; 7 class num { 8 public: 9 int n;//位数 10 int p[55] = {}; 11 num(int inn=0):n(inn){} 12 num(const num&A) { 13 n = A.n; 14 if (n == INF)return; 15 for (int i = 0; i < n; i++) 16 p[i] = A.p[i]; 17 } 18 num(string s) { 19 n = s.length(); 20 for (int i = 0; i < n; i++) 21 p[i] = s[i] - '0'; 22 } 23 num(int inn,int a[]) { 24 n = inn; 25 for (int i = 0; i < n; i++) 26 p[i] = a[n - 1 - i]; 27 } 28 num operator+(const num&A) { 29 if (n == INF) 30 return *this; 31 if (A.n == INF) 32 return A; 33 int factora[55] = {}, factorb[55] = {}, result[55] = {}; 34 for (int i = 0; i < A.n; i++) 35 factora[A.n - i-1] = A.p[i]; 36 for (int i = 0; i < n; i++) 37 factorb[n - 1 - i] = p[i]; 38 int maxc = max(n, A.n); 39 for (int i = 0; i < maxc; i++) 40 { 41 int temp = factora[i] + factorb[i] + result[i]; 42 result[i] = temp % 10; 43 result[i + 1] += temp / 10; 44 } 45 if (result[maxc] > 0) 46 maxc++; 47 return num(maxc, result); 48 } 49 bool operator <(const num&A) { 50 if (n != A.n) 51 return n < A.n; 52 for (int i = 0; i < n; i++) 53 { 54 if (p[i] != A.p[i]) 55 return p[i] < A.p[i]; 56 } 57 return false; 58 } 59 friend ostream&operator<<(ostream&o, const num&A) { 60 for (int i = 0; i < A.n; i++) 61 o << A.p[i]; 62 return o; 63 } 64 }; 65 num dp[55][55];//dp[i][j]表示在j个数字中插入i个加号能形成的表达式最小值 66 int main() 67 { 68 int m; 69 while (cin >> m) { 70 string s; 71 cin >> s; 72 int len = s.length(); 73 for (int i = 1; i <= len; i++) { 74 dp[0][i] = num(s.substr(0, i)); 75 } 76 for (int i = 1; i <= m; i++) { 77 for (int j = 1; j <= i; j++) 78 dp[i][j] = num(INF); 79 for (int j = i + 1; j <= len; j++) { 80 dp[i][j] = dp[i - 1][i] + num(s.substr(i, j - i)); 81 for (int k = i + 1; k <= j - 1; k++) 82 { 83 num temp = dp[i - 1][k] + num(s.substr(k, j - k)); 84 if (temp < dp[i][j]) 85 dp[i][j] = temp; 86 } 87 } 88 } 89 cout << dp[m][len] << endl; 90 } 91 92 }
标签:4152,输出,数字,整数,考点,加号,加法,include 来源: https://www.cnblogs.com/erable/p/14992087.html