您的位置:首页 > 其它

最佳加法表达式(动态规划)

2018-03-02 16:39 453 查看

最佳加法表达式

有一个由1..9组成的数字串.问如果将m个加 号插入到这个数字串中,在各种可能形成的 表达式中,值最小的那个表达式的值是多少

输入

1234 2

12345 3

输出

19

24

问题分析

要解决dp类问题,当然是要找子问题,确定目标状态的啦。

现在有n个数字组成的数字串,将m个加号插入里面求表达式的最小值。不如我们将其分解为两部分,第m个加号后面最后一项和前m-1个加号所组成的表达式。假设我们将最后一个加号填到了第i个数字后面,那么第i+1->n这一项的值就是可以确定的,那么问题就变成了求将m-1个加号填入到前面i个数字里所组成的表达式的最小值,然后递归去解决。

但是要想一下边界情况喔,当m减到0时,返回的是什么?当然应该是当前状态n个数字所组成的值喽。还有m的上界,一共n个数字,当然加号不能超过n-1个啦,如果超过了我们返回正无穷来表示无解。

设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),可以预处理后存起来。 总时间复杂度:O(mn^2)

预处理方式

cin>>n>>m;
int k = length(n);
for(int i = k-1; i >= 0; i--)
{
s[i] = n%10+'0';
n/=10;
}
for(int i = 1; i <= k; i++)
{
num[i][i] = s[i-1]-'0';
for(int j = i+1; j <= k; j++)
{
num[i][j] = nu
c242
m[i][j-1]*10+s[j-1]-'0';
}
}


递归方式

int v(int m,int n)
{
if(m==0)
return num[1]
;
else if(n<m+1)
return 0x3f3f3f3f;
else
{
int min1 = 0x3f3f3f3f;
for(int i = m; i <= n-1; i++)
min1 = min(v(m-1,i)+num[i+1]
,min1);
return min1;
}
}


递归转递推

memset(dp,0x3f,sizeof dp);
for(int i = 1; i <= n; i++)//当没有加号时
dp[0][i] = num[1][i];
for(int i = 1; i <= m; i++)
{
for(int j = i; j <= n; j++)
{
for(int l = i; l <= j; l++)
dp[i][j] = min(dp[i][j],dp[i-1][l]+num[l+1][j]);
}
}
cout<<dp[m]
<<endl;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: