0818 OpenJ#13295 最佳加法表达式

来源:互联网 发布:淘宝旺旺怎么加好友 编辑:程序博客网 时间:2024/06/05 22:32
摘要
-通过在大整数中添加加号使数字的值最小
原题目摘要
-最佳加法表达式

-
描述

给定n个1到9的数字,要求在数字之间摆放m个加号(加号两边必须有数字),使得所得到的加法表达式的值最小,并输出该值。例如,在1234中摆放1个加号,最好的摆法就是12+34,和为36

输入
有不超过15组数据
每组数据两行。第一行是整数m,表示有m个加号要放( 0<=m<=50)
第二行是若干个数字。数字总数n不超过50,且 m <= n-1
输出
对每组数据,输出最小加法表达式的值
样例输入
21234561123456412345
样例输出
10257915
提示
要用到高精度计算,即用数组来存放long long 都装不下的大整数,并用模拟列竖式的办法进行大整数的加法。


题目理解
-使用大整数加法来计算各种可能的情况。计算过程中保存计算过的值以供再利用
注意
dp数组在每一组数据的计算都要刷新 不然用了以前的数据就会出错;
BIGINT在重载比较的过程中 注意小于的定义。
日期
-
附加
-定义了大整数结构 重载+ < 运算符。
代码
#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <memory>using namespace std;#define MAX 80struct BIGINT{    char NUM[MAX];    BIGINT(){clean(NUM,MAX);setval("N");}    void setval(char *str){        clean(NUM,MAX);        strcpy(NUM,str);}    int cadd(char a,char b){        if(a=='\0') return b-'0';        if(b=='\0') return a-'0';        return a+b-2*'0';    }    void clean(char *str,int len){ memset(str,'\0',len*sizeof(char));}    void rev(char *str){reverse(str,str+strlen(str));}    void add(char *a,char *b,char *ans){        //align        rev(a);rev(b);        int tick=0,cnt,last=0;        while(!(a[tick]=='\0'&&b[tick]=='\0')){            cnt = cadd(a[tick],b[tick])+last;            ans[tick]=cnt%10+'0';            last=cnt/10;            tick++;        }        if(last!=0)ans[tick]=last+'0';        rev(a),rev(b),rev(ans);    }        BIGINT operator +(BIGINT &B){        //a,b,should be '\0'after num        BIGINT ANS;        char ans[MAX];clean(ans,MAX);        add(NUM,B.NUM,ANS.NUM);        return ANS;    }    bool operator <(BIGINT &B){        if(NUM[0]=='I') return false;        if(B.NUM[0]=='I') return true;        if(strlen(NUM)<strlen(B.NUM)) return true;        if(strlen(NUM)==strlen(B.NUM)){            int tick=0;            while(NUM[tick]!='\0'){                if(NUM[tick] < B.NUM[tick])return true;                else if(NUM[tick] > B.NUM[tick])return false;                tick++;            }        }        return false;    }};char num[MAX];BIGINT getvar(int l,int r){//[0,1]    char temp[MAX];    memcpy(temp,num+l,(r-l+1)*sizeof(char));    temp[r-l+1]='\0';    BIGINT ret;ret.setval(temp);    return ret;}BIGINT dp[MAX][MAX];BIGINT findmin(int n,int m){//[0,n] m+    if(dp[n][m].NUM[0]!='N') return dp[n][m];    BIGINT ans,t,r,l;    ans.setval("INF");//INF    if(n<m) return dp[n][m]=ans;    if(m==0) return dp[n][m]=getvar(0,n);    for(int i=1;n-i>=m-1;i++){//add + after num[n-i]        l=findmin(n-i,m-1);        r=getvar(n-i+1,n);        t=l+r;        ans =( t < ans ? t :ans);    }    return dp[n][m]=ans;}int main(){    int m;    while(~scanf("%d%s",&m,num)){        for(int i=0;i<MAX;i++){            for(int j=0;j<MAX;j++) dp[i][j].setval("NO");        }        cout<<findmin(strlen(num)-1,m).NUM<<endl;    }    return 0;}