3415 最小和

3415 最小和

链接:http://codevs.cn/problem/3415/

 

CodeVS原创

 时间限制: 1 s
 空间限制: 64000 KB
 
 
 
 
题目描述 Description

小浣熊松松来到文具店,选择了K支自己喜欢的水彩笔,并抄下了它们的价格。可是到结算时,他发现自己抄价格时抄得太密集,以至于所有价格连成了一个数字串(你可以假设价格都是正整数)。老板想和松松开个玩笑,于是对他说:“你可以把这个数字串分成K段,代表这K支笔的价格,然后把他们加起来,就是你要付给我的钱了。”当然,松松想尽可能省下钱去买《算法导论》,所以请你来帮忙算算,他最少需要付多少钱。

输入描述 Input Description

第一行包含一个整数N,代表松松抄下来的数字串。

第二行包含一个整数K,代表松松买了K支水彩笔。

输出描述 Output Description

输出仅一行,为松松买这些笔最少花的钱。

样例输入 Sample Input

79846

3

样例输出 Sample Output

133

数据范围及提示 Data Size & Hint

对于20%的数据,K=1;

对于100%的数据,数字串长度不超过8,K<=数字串长度。

由于是松松来划分,因此可以出现有前导0的价格,或者价格就是0。

题解:用f[i][k]表示用前i个数字组成K个价格的最小价格,h[i][j]表示第i到j个数字组成的价格;可以得到以下公式

 f[i][k]=min(f[j][k-1]+h[j+1][i],f[i][k])
#include<iostream>
using namespace std;
string s;
int N;
int f[10][10],h[10][10];
int m(int st,int ed){
    int c=1,ans=0;
    for(int i=ed;i>=st;i--){    
        ans+=(s[i]-'0')*c;
        c*=10;
    }
    return ans;
}
int main(){
    cin>>s>>N;
    int maxx=2*10e8;
    int l=s.length();
    for(int i=0;i<l;i++)
        for(int j=0;j<l;j++)h[i][j]=m(i,j);
    for(int i=0;i<l;i++)
        for(int k=1;k<=N;k++){
            if(k==1)f[i][k]=h[0][i];
            else f[i][k]=maxx;
        }
        
    for(int k=2;k<=N;k++)
        for(int i=0;i<l;i++)
            for(int j=k-2;j<=i-1;j++){
            f[i][k]=min(f[j][k-1]+h[j+1][i],f[i][k]);
        }
    cout<<f[l-1][N]<<endl;    
}
原文地址:https://www.cnblogs.com/EdSheeran/p/7454826.html