008:最佳加法表达式
-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
-
给定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
-
- 动规加高精度
-
-
#include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<iomanip> #include<queue> #include<stack> #include<vector> #include<set> #include<map> using namespace std; const int Maxlen=55; int m; string s; string maxv="999999999999999999999999999999999999999999999999999999999"; string dp[Maxlen][Maxlen]; string num[Maxlen][Maxlen]; int cmp(string &num1,string &num2) { int len1=num1.length(),len2=num2.length(); if(len1!=len2) { return len1-len2; } for(int i=len1-1;i>=0;--i) { if(num1[i]!=num2[i]) { return num1[i]-num2[i]; } } return 0; } void add(string& num1,string &num2,string&num3) { int len1=num1.length(),len2=num2.length(); int c=0; for(int i=0;i<Maxlen;++i) { int t; if(i<len1&&i<len2) { t=num1[i]-'0'+num2[i]-'0'+c; } else if(i<len1&&i>=len2) { t=num1[i]-'0'+c; } else if(i<len2&&i>=len1) { t=num2[i]-'0'+c; } else { break; } num3.append(1,t%10+'0'); c=t/10; } while(c) { num3.append(1,c%10+'0'); c=c/10; } } int main() { while(cin>>m>>s) { reverse(s.begin(),s.end()); int len=s.length(); for(int i=1;i<=len;++i) { for(int j=i;j<=len;++j) { num[i][j]=s.substr(i-1,j-i+1); } } for(int i=1;i<=len;++i) { dp[0][i]=num[1][i]; } for(int i=1;i<=m;++i) { for(int j=i+1;j<=len;++j) { string minv=maxv; string tmp; for(int k=i;k<=j-1;++k) { tmp.clear(); add(dp[i-1][k],num[k+1][j],tmp); if(cmp(minv,tmp)>0) { minv=tmp; } } dp[i][j]=minv; } } reverse(dp[m][len].begin(),dp[m][len].end()); cout<<dp[m][len]<<endl; } return 0; }