动态规划--(加法表达式)

描述:

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

输入:

5 3

1 2 3 4 5

输出:

24


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),可以预处理后存起来。 


#include<iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define SU 9999999


#define NUM 101
using namespace std;
    //递推
int main()
{
    int A[100];
    int result[2][NUM];//利用滚动数组来解决储存问题;
    int num[NUM][NUM];

    int n,m;

    cin>>n>>m;
    for(int i = 1;i<=n;i++)
        cin>>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];
    }//将所有的数字存储在数组num中;

//    for(int i = 1;i<=n;i++){
//        for(int j =1;j<=n;j++)
//            cout <<num[i][j]<<" ";
//        cout<< endl;
//    }//数值的转换测试;




        //初始化;
    for(int i = 1;i<=n;i++)
        result[0][i] = num[1][i];//如果是m= 0;
    for(int i = 1;i<=m;i++)
        result[i][0] = SU;
    result[0][0] = 0;


    for(int i = 1;i<=m;i++){//表示加号的个数;
        for(int j =1;j<=n;j++){//表示数的个数;
            if(i>=n)//加号过多;
                result[i%2][j] = SU;
            else{
                result[i%2][j]   = SU;
                for(int k = i;k<j;k++)
                    result[i%2][j] = min(result[i%2][j],result[(i-1)%2][k]+num[k+1][j]);
            }
        }

//    for(int i = 0;i<2;i++){
//        for(int j = 0;j<=n;j++)
//            printf("%-10d ",result[i][j]);
//        cout<<endl;
//    }//测试
//        cout <<" +++++++++++++++++++++++++++++++"<<endl;
//

    }


    cout <<result[m%2][n]<<endl;


    return 0;
}
点赞