1. 程式人生 > >數字串新增號求最小和

數字串新增號求最小和

轉載至https://blog.csdn.net/liuchaohs/article/details/53186735

題目描述

有一個由數字1,2,...,9組成的數字串(長度不超過200),問如何M(1<=M<=20)個加號插入這個數字串中,使得所形成的算術表示式的值最小。

注意:(1)加號不能加在數字串的最前面或最末尾,也不應有兩個或兩個以上的加號相鄰;

     (2)M保證小於數字串的長度。

  例如:數字串79846,若需加入兩個加號,則最佳方案是79+8+46,算術表示式的值是133。

  輸入格式:從鍵盤讀入輸入檔名。數字串在輸入檔案的第一行行首(數字串中間無空格且不換行),M的值在輸入檔案的第二行行首。

  輸出格式:在螢幕上輸出最小的和
解題思路:

規 劃 方 程 :

Dp[p,x] = MIN { dp[k,x-1] + NUM[K,p] } (x<=K<=p-I)

邊 界 值 :dp [p, 0 ]: = NUM[0, p]

Dp[p,x ]表 示前 p個 數 字 中 添 上 x個 加 號 後 得 到 的 最 小 值 。

NUM[x,y ]表 示數 字 串 [x.y) 的 數 
解題程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200;
const int inf=0x3f3f3f3f;
int dp[N][N];
int num[N][N];
int m;
char ch[N];
int NUM(int k,int p){
    if(num[k][p]!=-1)
        return num[k][p];
    int sum=0;
    for(int i=k;i<p;i++){
        sum=sum*10+ch[i]-'0';
    }
    num[k][p]=sum;
    return sum;
}
int DP(int p,int x){
    if(dp[p][x]!=-1)
        return dp[p][x];
    if(x==0){
        dp[p][0]=NUM(0,p);
        return dp[p][0];
    }
    dp[p][x]=inf;
    for(int i=p-1;i>=x;i--){
      dp[p][x]=min(dp[p][x],DP(i,x-1)+NUM(i,p));
    }
    return dp[p][x];
}
int main(){
    memset(dp,-1,sizeof(dp));
    memset(num,-1,sizeof(num));
    scanf("%s",ch);
    scanf("%d",&m);
    int len=strlen(ch);
    printf("%d\n",DP(len,m));
return 0;
}