给定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[i][j]表示前i个数添加了j个加号得到的最小和。转移方程为 dp[i][j]=min(dp[x][j-1]+num[x+1][i]) 其中x>=j且x<i num[x+1][i]表示第x+1位到第i位组成的数。
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <queue> 8 #include <set> 9 #include <map> 10 #include <list> 11 #include <vector> 12 #include <stack> 13 #define mp make_pair 14 //#define P make_pair 15 #define MIN(a,b) (a>b?b:a) 16 //#define MAX(a,b) (a>b?a:b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int MAX=1e2+5; 20 const int INF=1e8+5; 21 using namespace std; 22 //const int MOD=1e9+7; 23 typedef pair<ll,int> pii; 24 const double eps=0.00000001; 25 26 string add(string x,string y) 27 { 28 string re; 29 int jin=0; 30 for(int i=x.length()-1,j=y.length()-1;i>=0||j>=0;i--,j--) 31 { 32 re=" "+re; 33 re[0]=(i>=0?x[i]-'0':0)+(j>=0?y[j]-'0':0)+jin; 34 if(re[0]>=10) 35 jin=1,re[0]=(re[0]%10)+'0'; 36 else 37 jin=0,re[0]=re[0]+'0'; 38 } 39 if(jin) 40 re='1'+re; 41 return re; 42 } 43 string mins(string x,string y) 44 { 45 if(x.length()<y.length()) 46 return x; 47 else if(y.length()<x.length()) 48 return y; 49 else return x<y?x:y; 50 } 51 int m; 52 string x; 53 string dp[55][55]; 54 int main() 55 { 56 while(~scanf("%d",&m)) 57 { 58 cin>>x; 59 int len=x.length(); 60 x=" "+x; 61 for(int i=0;i<=len;i++) 62 dp[i][0]=x.substr(1,i); 63 for(int j=1;j<=m;j++) 64 for(int i=j+1;i<=len;i++) 65 for(int s=j;s<i;s++) 66 { 67 if(s==j) 68 dp[i][j]=add(dp[s][j-1],x.substr(s+1,i-s)); 69 else 70 dp[i][j]=mins(dp[i][j],add(dp[s][j-1],x.substr(s+1,i-s))); 71 } 72 cout<<dp[len][m]<<" "; 73 } 74 }