最佳加法表达式
2020-04-22 16:55
267 查看
最佳加法表达式
题目描述
有一个由1…9组成的数字串.问如果将m个加号插入到这个数字串中,在各种可能形成的表达式中,值最小的那个表达式的值是多少。
输入:
5 3
1 2 3 4 5
输出:
24
我们一开始可以采用递归的思路来进行思考。
我们先考虑,最右边的加号放在哪里?
假设数字字符2长度为n,最右边的加号放在第i个数字的后边.
那么现在最小值就是在前i个数字中插入m-1个加号后所能形成的最小值.
那么现在就是减而治之的递归思路就完成了(分解为规模更小的子问题来解决)
这也恰恰满足我们的最优子结构和无后效性
V(m,n)表示前n个数组当中插入m个加号所形成表达式最小值
下面借用以下人家的分析:
设V(m,n)表示在n个数字中插入m个加号所能形成
的表达式最小值,那么:
if m = 0
V(m,n) = n个数字构成的整数
else if n < m + 1
V(m,n) = ∞(不是所求就是最大的)
else
V(m,n) = Min{ V(m-1,i) + num(i+1,n) } ( i = m … n-1)
num(i,j)表示从第i个数字到第j个数字所组成的数。数字编号从1开始算。此操作复杂度是O(j-i+1),为了节省时间我们预处理num(i,j)(就是什么都不干之前把这些值全部算出来)
总时间复杂度:O(mn^2) .
有的题目需要用到高精度模板来进行计算了(long long无法承受得住的时候)高精度模板可以参考我教主的序列的文章
这里我想说的是,你一旦用高精度模板,那么将会变成O(mn^3),应为多了n个元素的数组,你每次操作数组都是O(n)的
递归型代码
#include <iostream>//最佳加法表达式 #include <cstring> #include <algorithm> #include <cstdio> const int INF=9999999; int a[1010],num[1010][1010]; using namespace std; int V(int m,int n) {//状态转移方程 if(m==0) return num[1][n]; else if(n<m+1)//加号多了 return INF; else { int t = INF; for(int i = m;i <= n-1;i++) t = min(t, V(m-1,i)+num[i+1][n]); return t; } } int main() { int n,m; while(~scanf("%d%d",&n,&m))//就是当没有输入的时候退出循环 { for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=n;++i)//预处理,节省时间 { num[i][i]=a[i];//只有一个数组 for(int j=i+1;j<=n;++j) { num[i][j]=num[i][j-1]*10+a[j]; } } cout<<V(m,n)<<endl; } return 0; }
递推型的可以自己想一下哦
递推型
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f;//无穷大 const int N=1010; int a[N],num[N][N],dp[N][N]; //a 里面是存数字串 //num[i][j]表示数字串a 的第i位到第j位之间的数字串表示的数组 int main(){ int n,m; while(scanf("%d %d",&n,&m)){ for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } //预处理,计算i到j数字串组成的数字 for(int i=1;i<=n;i++){ num[i][i]=a[i];//只有一个数字 for(int j=i+1;j<=n;j++){ num[i][j]=num[i][j-1]*10+a[j]; } } memset(dp,0x3f,sizeof(dp)); for(int i=1;i<=n;i++){ dp[0][i]=num[1][i];//无加号时 } //这里n可以写在m前面。要加一个限制条件n>m,好麻烦,所以m在前且n=m+1 //这里k的取值范围就是m到n,k表示在第k个数后面插入加号 for(int i=1;i<=m;i++) for(int j=i;j<=n;j++) for(int k=i;k<=j;k++) dp[i][j]=min(dp[i][j],dp[i-1][k]+num[k+1][j]); cout<<dp[m][n]<<endl; } }
学会程序和算法,走遍天下都不怕
广西桂林
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 程序设计与算法(二)测验汇总011:最佳加法表达式(DP、高精度)
- 最佳加法表达式
- 最佳加法表达式(动态规划)
- 最佳加法表达式 dp
- 最佳加法表达式
- 最佳加法表达式
- 2020.2.11动态规划/记忆递归总结+例题(1191棋盘分割 1661帮助jimmy 2760数字三角形 4152最佳加法表达式 2757最长上升子序列 1458Common Subsequen)
- 最佳加法表达式
- 递推,动态规划(DP),字符串处理,最佳加法表达式
- 最佳加法表达式
- 最佳加法表达式(dp)
- dp 最佳加法表达式
- 最佳加法表达式(动态规划)
- dp 最佳加法表达式
- 最佳加法表达式——老师的题解(很难)!
- 最佳加法表达式(动态规划)
- 动态规划(3):熟练度练习(POJ 1458、最佳加法表达式、bailian2755、POJ3624、bailian1088)
- 动态规划之最佳加法表达式
- 最佳加法表达式(动态规划)
- 【每日打卡】Day15:最佳加法表达式(大数运算)JAVA实现(部分超时)