最佳加法表达式POJ

B:最佳加法表达式​​​​​​

总时间限制: 

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 都装不下的大整数,并用模拟列竖式的办法进行大整数的加法。

呜呜,快要哭死了,一道题写了两天,一直不知道是哪里WA了,最后做后才发现是小于函数重载写错了。(你浪费我这么多时间呜呜)

所以说写代码的时候一定要注意细节,每写一个小函数都要随时检验,否则最后RTE或是WA时就会很难堪!

#include <iostream>
#include <string>
#define MAX 60
#define INF Int("99999999999999999999999999999999999999999999999999999")
using namespace std;

class Int
{
    string str;
public:
    Int(string s = "") : str(s) {}
    bool empty()
    {
        return str.empty();
    }
    void reset()
    {
        str = "";
    }
    friend Int operator+(const Int &x, const Int &y)
    {
        int temp[MAX]{};
        int cnt = 0;
        int i = x.str.size(), j = y.str.size();
        while (i > 0 && j > 0)
        {
            temp[cnt++] = x.str[--i] + y.str[--j] - 2 * '0';
        }
        if (i != j)
        {
            while (i > 0)
                temp[cnt++] = x.str[--i] - '0';
            while (j > 0)
                temp[cnt++] = y.str[--j] - '0';
        }
        for (int k = 0; k < cnt; ++k)
        {
            temp[k + 1] += temp[k] / 10;
            temp[k] %= 10;
        }
        if (temp[cnt])
            ++cnt;
        string str;
        while (cnt)
            str += temp[--cnt] + '0';
        return Int(str);
    }
    friend bool operator<(const Int &x, const Int &y)
    {
        if (x.str.size() == y.str.size())
        {
            for (int i = 0; i < x.str.size(); ++i)
            {
                if (x.str[i] < y.str[i])
                    return 1;
                else if (x.str[i] > y.str[i])
                    return 0;
            }
            return 0;
        }
        else
            return x.str.size() < y.str.size();
    }
    friend ostream &operator<<(ostream &o, const Int &i)
    {
        o << i.str;
        return o;
    }
};

Int visited[MAX][MAX];
int m;
string str;
Int num(int begin, int end)
{
    return Int(str.substr(begin, end - begin));
}
Int calc(int n, int m)
{
    if (!visited[n][m].empty())
        return visited[n][m];
    Int ret;
    if (m == 0)
        ret = num(0, n);
    else
    {
        ret = INF;
        for (int i = m; i < n; ++i)
            ret = min(ret, calc(i, m - 1) + num(i, n));
    }
    return visited[n][m] = ret;
}

int main()
{
    while (cin >> m >> str)
    {
        for (int i = 0; i < MAX; ++i)
            for (int j = 0; j < MAX; ++j)
                visited[i][j].reset();
        cout << calc(str.size(), m) << endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值