总时间限制: 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. 项目Beta冲刺——凡事预则立

    班级:软件工程1916|W 作业:项目Beta冲刺(团队) 团队名称:Echo 作业目标:规定代码规范,明确冲刺任务与计划 目录 团队博客汇总 讨论组长是否重选的议题和结论 下一阶段需要改进完善的功能 ...

  2. jmeter-多用户循环执行(存储token)

    1.从cvs文件中读取数据 登录接口读取文件: 2.读取token,保存token 在登录接口下添加 设置: 把token保存为全局变量: 设置: 输入${__setProperty(newtoken ...

  3. HDU - 3535:AreYouBusy (分组背包)

    题意:给你n个工作集合,给你T的时间去做它们.给你m和s,说明这个工作集合有m件事可以做,它们是s类的工作集合(s=0,1,2,s=0说明这m件事中最少得做一件,s=1说明这m件事中最多只能做一件,s ...

  4. Celery + Redis 的探究

    Celery + Redis 的探究 文本尝试研究,使用 redis 作为 celery 的 broker 时,celery 的交互操作同 redis 中数据记录的关联关系. 不在乎过程的,可以直接看 ...

  5. Vue --- 前后台总结

    请求生命周期: 1.先请求路由,在去替换APP.vue中的router-views 2.@表示src 3.加载全局css: require('@/assets/....') 4.获取当前路由 this ...

  6. 51nod1423 最大二“货”

    [传送门] 单调栈其实就是个后缀$max/min$,这道题可以维护一个单调递减的单调栈,pop元素的时候,能pop掉的元素就是第二大,当前元素为第一大.遇到第一个不能pop掉的时候当前元素就是第二大, ...

  7. c++实用语法

    数组的快捷初始化 int inq[110] memset(inq, 0, sizeof(inq)); string到char数组的转换: string str ("Please split ...

  8. 11、 Hadoop 2.x各个服务组件如何配置在那台服务器运行并测试

    HDFS模块 NameNode:是由哪个文件中的哪个配置属性指定的呢? core-site.xml文件中: <property> <name>fs.defaultFS</ ...

  9. 项目集成Spring Security

    前言 之前写的 涂涂影院管理系统 这个 demo 是基于 shiro 来鉴权的,项目前后端分离后,显然集成 Spring Security 更加方便一些,毕竟,都用 Spring 了,权限管理当然 S ...

  10. (尚024)Vue_案例_交互删除

    注意:本总结中最终会删除不成功 ,原因是Item.vue中方法methods单词拼写错误!!! 首先明白,删除在Item.vue中交互 1.写交互,首先写监听@click="deleteIt ...