总时间限制: 1000ms 内存限制: 65536kB

描述

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

输入

有不超过15组数据
每组数据两行。第一行是整数m,表示有m个加号要放( 0<=m<=50)
第二行是若干个数字。数字总数n不超过50,且 m <= n-1

输出

对每组数据,输出最小加法表达式的值

样例输入


样例输出


提示

要用到高精度计算,即用数组来存放long long 都装不下的大整数,并用模拟列竖式的办法进行大整数的加法。

解题思路

主要难点在高精度计算,以下提供两种解法,码着日后研究。

AC代码一

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
struct BigInt
{
int num[];
int len;
BigInt operator+(const BigInt & n) { //重载+,使得 a + b在 a,b都是 BigInt变量的时候能成立
int ml = max(len,n.len);
int carry = ; //进位
BigInt result;
for(int i = ;i < ml; ++i) {
result.num[i] = num[i] + n.num[i] + carry;
if( result.num[i] >= ) {
carry = ;
result.num[i] -= ;
}
else
carry = ;
}
if ( carry == ) {
result.len = ml + ;
result.num[ml] = ;
}
else
result.len = ml;
return result;
}
bool operator<(const BigInt & n) {
if( len > n.len )
return false;
else if( len < n.len)
return true;
else {
for(int i = len -; i >= ; -- i) {
if( num[i] < n.num[i])
return true;
else if( num[i] > n.num[i])
return false;
}
return false;
}
}
BigInt() {
len = ;
memset(num,,sizeof(num));
}
BigInt(const char * n,int L) { //由长度为L的char数组构造大整数。n里面的元素取值范围从 1-9。
memset(num,,sizeof(num));
len = L;
for(int i = ; n[i]; ++i)
num[len-i-] = n[i] - '';
}
};
ostream & operator <<(ostream & o,const BigInt & n)
{ for(int i = n.len - ;i >= ; --i)
o << n.num[i];
return o;
}
const int MAXN = ;
char a[MAXN];
BigInt Num[MAXN][MAXN];//Num[i][j]表示从第i个数字到第j个数字所构成的整数
BigInt V[MAXN][MAXN]; //V[i][j]表示i个加号放到前j个数字中间,所能得到的最佳表达式的值。
int main()
{
int m,n;
BigInt inf; //无穷大
inf.num[MAXN-] = ;
inf.len = MAXN-; while(cin >> m ) {
cin >> a+;
n = strlen(a+);
for(int i = ;i <= n; ++i)
for(int j = i;j<= n; ++j) {
Num[i][j] = BigInt(a+i,j-i+);
}
for(int j = ; j <= n; ++j) {
V[][j] = BigInt(a+,j);
} for(int i = ;i <= m; ++i) {
for(int j = ; j <= n; ++j) {
if( j - < i)
V[i][j] = inf;
else {
BigInt tmpMin = inf;
for(int k = i; k < j; ++k) {
BigInt tmp = V[i-][k] + Num[k+][j];
if (tmp < tmpMin)
tmpMin = tmp;
}
V[i][j] = tmpMin;
}
}
}
cout << V[m][n] << endl;
}
return ;
}

AC代码二

#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <list>
#include <vector>
#include <stack>
#define mp make_pair
//#define P make_pair
#define MIN(a,b) (a>b?b:a)
//#define MAX(a,b) (a>b?a:b)
typedef long long ll;
typedef unsigned long long ull;
const int MAX=1e2+;
const int INF=1e8+;
using namespace std;
//const int MOD=1e9+7;
typedef pair<ll,int> pii;
const double eps=0.00000001; string add(string x,string y)
{
string re;
int jin=;
for(int i=x.length()-,j=y.length()-;i>=||j>=;i--,j--)
{
re=" "+re;
re[]=(i>=?x[i]-'':)+(j>=?y[j]-'':)+jin;
if(re[]>=)
jin=,re[]=(re[]%)+'';
else
jin=,re[]=re[]+'';
}
if(jin)
re=''+re;
return re;
}
string mins(string x,string y)
{
if(x.length()<y.length())
return x;
else if(y.length()<x.length())
return y;
else return x<y?x:y;
}
int m;
string x;
string dp[][];
int main()
{
while(~scanf("%d",&m))
{
cin>>x;
int len=x.length();
x=" "+x;
for(int i=;i<=len;i++)
dp[i][]=x.substr(,i);
for(int j=;j<=m;j++)
for(int i=j+;i<=len;i++)
for(int s=j;s<i;s++)
{
if(s==j)
dp[i][j]=add(dp[s][j-],x.substr(s+,i-s));
else
dp[i][j]=mins(dp[i][j],add(dp[s][j-],x.substr(s+,i-s)));
}
cout<<dp[len][m]<<"\n";
}
}

参考网址

https://blog.csdn.net/qq_43472263/article/details/88652211

https://www.cnblogs.com/huashanqingzhu/p/8097787.html

OpenJudge 4152 最佳加法表达式的更多相关文章

  1. 百练4152:最佳加法表达式(dp+高精度)

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

  2. OpenJ_Bailian - 4152 最佳加法表达式 dp

    http://bailian.openjudge.cn/practice/4152?lang=en_US 题解 :dp[i][j]代表前i个字符加j个加号可以得到的最小值,于是dp[i+k[j+1]可 ...

  3. 【OpenJ_Bailian - 4152 】最佳加法表达式(动态规划)

    最佳加法表达式 Descriptions: 给定n个1到9的数字,要求在数字之间摆放m个加号(加号两边必须有数字),使得所得到的加法表达式的值最小,并输出该值.例如,在1234中摆放1个加号,最好的摆 ...

  4. dp 动规 最佳加法表达式

    最佳加法表达式 有一个由1..9组成的数字串.问如果将m个加号插入到这个数字串中,在各种可能形成的表达式中,值最小的那个表达式的值是多少 解题思路 假定数字串长度是n,添完加号后,表达式的最后一个加号 ...

  5. 【动态规划】最佳加法表达式(百练oj4152)

    总时间限制: 1000ms 内存限制: 65536kB 描述 给定n个1到9的数字,要求在数字之间摆放m个加号(加号两边必须有数字),使得所得到的加法表达式的值最小,并输出该值.例如,在1234中摆放 ...

  6. 最佳加法表达式(dp)

    题目描述: 有一个由1..9组成的数字串.问如果将m个加 号插入到这个数字串中,在各种可能形成的 表达式中,值最小的那个表达式的值是多少 (本题只能用于整数) 解题思路: 假定数字串长度是n,添完加号 ...

  7. 递推,动态规划(DP),字符串处理,最佳加法表达式

    看了一些资料,竟然发现连百度文库也有错误的地方,在这里吐槽一下题目大意:http://wenku.baidu.com/link?url=DrUNNm19IqpPNZjKPX4Jg6shJiK_Nho6 ...

  8. java源码——0~9十个数字不重复地使用使加法表达式成立

    这个问题是在我写个的几个博客里较为复杂的一个.首先,先看看整个问题的表述. 星号表示0~9的一个数字,而且不允许重复,使得下面的加法表达式成立.输出所有结果. ※ ※ ※ ※ ※    +  2   ...

  9. OpenJudge 2694 逆波兰表达式

    1.链接地址: http://bailian.openjudge.cn/practice/2694/ 2.题目: 总时间限制: 1000ms 内存限制: 65536kB 描述 逆波兰表达式是一种把运算 ...

随机推荐

  1. Zabbix4.0国内下载源

    国内zabbix源总结 目前发现的有以下几个站点: 1.阿里巴巴开源镜像站(推荐使用) 地址:https://mirrors.aliyun.com/zabbix/ 2.华为开源镜像站(推荐使用) 地址 ...

  2. Kafaka 总结

    Kafka是一个分布式的Streaming处理平台,Kafka可以用于数据库中数据的导入导出,也可以用于实时流的处理,但是Kafka最核心的功能就是作为分布式的消息中间件. Kafka集群是由多个Br ...

  3. 安装tomacat之后出现需要授权窗口

    安装tomacat之后登录网页,出现需要授权窗口,输入正确密码后依然会循环弹出该窗口. 原因: 因为tomcat的端口与oracle的端口重复了. 解决: 进入任务管理器,然后将oracle运行的程序 ...

  4. c#中的继承学习总结

    c#的继承方法,大体上和c++的类似,但是有点区别的,我这里刚刚初学,因此把重点记录下. 1.派生类继承了父类,那么,如果父类的方法和数据都是public,那么派生类都会继承.派生类可以直接调用父类的 ...

  5. ubuntu18.04 + python3 安装pip3

    最近在学习python 网络爬虫,正好接触到python的requests模块 我的开发环境是ubuntu18.04+python3,这个系统是默认自带了python3,且版本是python 3.6. ...

  6. OLED液晶屏幕(2)取模软件

    https://blog.csdn.net/ling3ye/article/details/53399305 文件夹说明: Adafruit_SSD1306-master   ——SSD1306库(O ...

  7. LeetCode 959. Regions Cut By Slashes

    原题链接在这里:https://leetcode.com/problems/regions-cut-by-slashes/ 题目: In a N x N grid composed of 1 x 1 ...

  8. 19-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 连接和断开

    https://www.cnblogs.com/yangfengwu/p/11130428.html 渐渐的看过去,,,好多节了... 这节做一个C# TCP客户端 新建项目啥子的就不详细截图写了,自 ...

  9. 树组件——jstree使用

    本文记录的只是我自己当时的代码,每行的注释很清楚了,你自己可以做相应变通 一.使用前提: 1.下载jstree依赖包 2.相关页面引入样式["jstree/themes/default/st ...

  10. Calibre中使用DeDRM插件进行Kindle电子书解锁

    小书匠 废话不多说,下面是Calibre和DeDRM插件的下载地址: https://calibre-ebook.com/download https://github.com/apprenticeh ...