【動態規劃】最佳加法表達式(百練oj4152)

總時間限制:
1000ms
內存限制:
65536kB
描述

給定n個1到9的數字,要求在數字之間擺放m個加號(加號兩邊必須有數字),使得所獲得的加法表達式的值最小,並輸出該值。例如,在1234中擺放1個加號,最好的擺法就是12+34,和爲36ios

輸入
有不超過15組數據
每組數據兩行。第一行是整數m,表示有m個加號要放( 0<=m<=50)
第二行是若干個數字。數字總數n不超過50,且 m <= n-1
輸出
對每組數據,輸出最小加法表達式的值
樣例輸入
2
123456
1
123456
4
12345
樣例輸出
102
579
15
提示
要用到高精度計算,即用數組來存放long long 都裝不下的大整數,並用模擬列豎式的辦法進行大整數的加法。
來源
Guo Wei

題解:

本題難點在於利用數組實現高精度運算,模擬加減乘除
假設數字串的長度爲 n,求將 m 個加號放入該字符串所造成的最小值
首先,分解子問題,規定最後一個加號的位置,假設將最後一個加號放在第 i 個數字後面,這時該問題就變成了在前i個數字中插入m - 1個加號所造成的最小值,加上第i + 1到第 n 個數字所組成的數的值( i 從 1 算起)
因此能夠定義一個字符串加的函數add,利用引用型參數傳遞值。 注意:字符串相加減,必定要注意高低位之分,能夠在以前將字符串反轉(可用STL中的 reverse(str.begin() , str.end()) 函數)
 1 void add(string &num1, string &num2, string &num3) {
 2     int l1 = num1.length();
 3     int l2 = num2.length();
 4     int c = 0;//進位標誌
 5     int maxl  = Maxlen;
 6     
 7     for(int i = 0; i < maxl; i++) {
 8         int t;
 9         if(i < l1 && i < l2) {
10             t = num1[i] + num2[i] - 2 * '0' + c;
11         }
12         else if(i < l1 && i >= l2) {
13             t = num1[i] - '0' + c;
14         }
15         else if(i >= l1 && i < l2) {
16             t = num2[i] - '0' + c;
17         }
18         else {
19             break;
20         }
21         num3.append(1, t % 10 + '0');
22         c = t / 10;
23     }
24     while (c)
25     {
26         num3.append(1,c%10+'0');
27         c /= 10;
28     }
29 }

 



總代碼:
 1 #include<iostream>
 2 using namespace std;
 3 #include<cstring>
 4 #include<string>
 5 #include<algorithm>
 6 #include<stdlib.h>
 7 
 8 const int Maxlen = 55;
 9 const string maxv = "9999999999999999999999999999999999999999999";
10 string ret[Maxlen][Maxlen];
11 string num[Maxlen][Maxlen];
12 
13 int cmp(string &num1, string &num2) {
14     int l1 = num1.length();
15     int l2 = num2.length();
16     if(l1 != l2) {
17         return (l1 - l2);
18     }
19     else {
20         for(int i = l1 - 1; i >= 0; i--) {
21             if(num1[i] != num2[i]) {
22                 return (num1[i] - num2[i]);
23             }
24         }
25         return 0;
26     }
27 }
28 
29 void add(string &num1, string &num2, string &num3) {
30     int l1 = num1.length();
31     int l2 = num2.length();
32     int c = 0;//進位標誌
33     int maxl  = Maxlen;
34     
35     for(int i = 0; i < maxl; i++) {
36         int t;
37         if(i < l1 && i < l2) {
38             t = num1[i] + num2[i] - 2 * '0' + c;
39         }
40         else if(i < l1 && i >= l2) {
41             t = num1[i] - '0' + c;
42         }
43         else if(i >= l1 && i < l2) {
44             t = num2[i] - '0' + c;
45         }
46         else {
47             break;
48         }
49         num3.append(1, t % 10 + '0');
50         c = t / 10;
51     }
52     while (c)
53     {
54         num3.append(1,c%10+'0');
55         c /= 10;
56     }
57 }
58 
59 int main() {
60     int m;
61     string str;
62     while(cin >> m >> str) {
63         //加法從低位到高位相加,那麼須要將字符串倒過來
64         reverse(str.begin(), str.end());
65         int n = str.length();
66         for(int i = 0; i < n; i++) {
67             num[i + 1][i + 1] = str.substr(i, 1);
68         }
69         for(int i = 1; i <= n; i++) {
70             for(int j = i + 1; j <= n; j++) {
71                 num[i][j] = str.substr(i - 1, j - i + 1);
72             }
73         }
74         
75         for(int i = 1; i <= n; i++) {//加號數目爲0的時候
76             ret[0][i] = num[1][i];
77         }
78         for(int i = 1; i <= m; i++) {
79             for(int j = 1; j <= n; j++) {
80                 string minv = maxv;
81                 string temp;
82                 for(int k = i; k <= j - 1; k++){//ret[m][n] = min(ret[m-1][i] + num[i+1][n]);
83                     temp.clear();
84                     add(ret[i - 1][k], num[k + 1][j], temp);
85                     if(cmp(temp, minv) < 0) {
86                         minv = temp;
87                     }
88                 }
89                 ret[i][j] = minv;
90             }
91         }
92         reverse(ret[m][n].begin(), ret[m][n].end());
93         cout << ret[m][n] << endl;
94     }
95     return 0;
96 }

 參考連接 https://blog.csdn.net/qq_35049196/article/details/58247829數組

相關文章
相關標籤/搜索