zoukankan      html  css  js  c++  java
  • dp练习(7)—— 最小和

    3415 最小和

     

    CodeVS原创

     时间限制: 1 s
     空间限制: 64000 KB
     题目等级 : 青铜 Bronze
     
     
     
    题目描述 Description

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

    输入描述 Input Description

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

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

    输出描述 Output Description

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

    样例输入 Sample Input

    79846

    3

    样例输出 Sample Output

    133

    先贴上代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    char N[10005];
    int k;
    long long dp[1005][1005];
    long long Count(int h,int i)
    {
        long long sum = 0;
        for(int j=h-1;j < i;j++)
        {
            sum = sum * 10 + (N[j] - '0') ;
        }
        return sum;
    
    }
    int main()
    {
        cin >> N >> k;
        memset(dp,INT8_MAX,sizeof(dp));
        for(int i=1;i <= strlen(N);i++)
        {
            dp[i][0] = Count(1,i);
    //        cout << dp[i][0] << endl;
        }
        for(int h=1;h <= k;h++) //h个乘号
        {
            for(int i=1;i <= strlen(N);i++)//到第i个数字
            {
                for(int j=1;j <= i;j++)//1~i之间走动的j
                {
                    dp[i][h] = min(dp[i][h],dp[j][h-1] + Count(j+1,i));
                }
            }
        }
        cout << dp[strlen(N)][k-1] << endl;
    //    for(int i=0;i < 6;i++)
    //    {
    //        for(int j=0;j < 6;j++)
    //            cout << dp[i][j] << " ";
    //        cout << endl;
    //    }
    
        return 0;
    }

    代码分析

    要搞懂这段代码首先要明白数组的含义

    h 代表的是有几个加号 , i 与 j 是经典动态规划里的东西 i 从1~n,j从1~i;

    那个函数的作用是把字符串拆分,执行第一处的测试输出得:

    (结合实例应该比较好理解)

    然后,是最重要的三个循坏:

    for(int h=1;h <= k;h++) //h个乘号
        {
            for(int i=1;i <= strlen(N);i++)//到第i个数字
            {
                for(int j=1;j <= i;j++)//1~i之间走动的j
                {
                    dp[i][h] = min(dp[i][h],dp[j][h-1] + Count(j+1,i));
                }
            }
        }

    借用了别人的图片来解释:

    dp[i][h] = min(dp[i][h],dp[j][h-1] + Count(j+1,i));
    dp[i][h]到第i个用了h个加号,dp[j][h-1] + Count(j+1,i) 就是上面这幅图的代码表示  

    测试结果,测试输出dp[][]:
    最后得到133
    (ps:有个注意点就是用min求最小值的时候要将数组初始化为INTMAX)
  • 相关阅读:
    LINUX安装 RPM与YUM
    ln s 软链接知识总结
    JQuery EasyUI 之 combobox plugin
    域名的DNS解析指南
    Asp.NET + OWC 输出Chart(图表)
    打败 IE 的葵花宝典:CSS Bug Table
    Route命令使用详解
    JQuery EasyUI 之 validatebox plugin
    JQuery easyUI 之 datebox plugin
    [转]如何安全的存储密码
  • 原文地址:https://www.cnblogs.com/cunyusup/p/8343754.html
Copyright © 2011-2022 走看看