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)
  • 相关阅读:
    C# 使用SqlBulkCopy类批量复制大数据 快速导入Excel大量数据
    Git的安装与使用
    未能加载文件或程序集“Microsoft.VisualStudio.Web.PageInspector.Loader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。
    Android SDK Manager不能显示所有包的解决办法
    editor多功能文本框在有些计算机上不能正常加载,解决方法,本人用的是把js调用方法放到<body></body>后面)
    MVC URL参数传递+变为空格解决方法
    SQL 查询不重复数据
    Java基本数据类型取值范围
    统计数组中的逆数对个数
    Docker 安装 ElasticSearch
  • 原文地址:https://www.cnblogs.com/cunyusup/p/8343754.html
Copyright © 2011-2022 走看看