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)

原文地址:https://www.cnblogs.com/cunyusup/p/8343754.html

时间: 2024-08-30 12:35:35

dp练习(7)—— 最小和的相关文章

树形DP 树的最小支配集,最小点覆盖与最大独立集

最小支配集: 从V中选取尽量少的点组成一个集合,让V中剩余的点都与取出来的点有边相连. (点) 最小点覆盖: 从V中选取尽量少的点组成一个集合V1,让所有边(u,v)中要么u属于V1,要么v属于V1 (边) 最大独立集: 从V中选取尽量多的点组成一个集合,让这些点中间没有边项链,也就是说对于任何一条边,u,v不能同时属于集合V1. 1.贪心算法 首先选取一个点为根节点,求出所有节点对应的DFS序列,按照所得序列反向进行贪心,这样保证对于每个点来说,当子树都被处理过之后才会处理该节点 int p[

[DP]矩阵的最小路径和

题目 给定一个矩阵m, 从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的树子累加起来就是路径和,返回所有的路径中最小的路径和. 解法一 这是一道经典的动态规划题,状态转移方程为dp[i][j] = min{dp[i - 1][j], dp[i][j - 1]} + m[i][j].可以用一个二维的dp矩阵来求解.对于dp矩阵,第一行和第一列只会有一种走法,就是从左到右或者从上到下的累加,所以可以先进行初始化,然后其他元素就可以用过转移方程一个一个填充,知道把整个dp矩阵填充

HDU 1227 dp距离和最小,中位数的应用

在n个商店中建m个仓库,使各个商店到仓库的路程之和最小,商店到哪个仓库是有选择的, 总之路程之和要最小! 思路: 从第i个商店到第j个商店建一个仓库,这个仓库所建的位置一定是dis[(i+j)/2],即建在它的中位数处, 所以,这个增加值就是case[i][j]=abs(dis[k]-dis[(i+j)/2])(i<=k<=j); 我们要把它初始为一个尽可能大的数,要找dp[i][j],首先dp[i][j]=10000000(尽可能的大):然后找前一个状态,dp[i-1][m] 为啥是m呢?因

简单Dp----最长公共子序列,DAG最长路,简单区间DP等

/* uva 111 * 题意: * 顺序有变化的最长公共子序列: * 模板: */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[100]; int mu[100]; int Dp[100][100]; int main() { int n,x; scanf("%d", &n

POJ - 3659 Cell Phone Network(树形dp---树的最小点支配集)

题意:有N个点,N-1条边,任意两点可达,由此形成了一棵树.选取一个点a,它可覆盖自己以及与自己相邻的点,选取尽量少的点a,使得树中所有点都被覆盖,即求树的最小点支配集. 分析: 1.对于每一个点cur,要想使其被覆盖,有三种情况: dp[cur][0]---在该点建立塔 dp[cur][1]---在该点的子结点建立塔 dp[cur][2]---在该点的父结点建立塔 2.对于点cur的子结点x,要使其被覆盖: (1)dp[cur][0] += Min(Min(dp[x][0], dp[x][1]

Doing Homework(HDU 1074状压dp)

题意:给你n个要做的作业,它们的名字.期限.可完成所需天数(必须连续)在规定期限不能完成要扣分(每天一分)求做作业顺序使扣分最少. 分析:作业数量较少,用状态压缩,做到第i种作业花费的天数dp[i].t,最小扣分dp[i].sc,当前完成作业标号dp[i].now,和之前完成的作业的情况dp[i].par(要求做作业顺序)枚举所有可能的情况,更新. #include <map> #include <set> #include <list> #include <cm

HDU 4968 Improving the GPA(dp)

HDU 4968 Improving the GPA 题目链接 dp,最大最小分别dp一次,dp[i][j]表示第i个人,还有j分的情况,分数可以减掉60最为状态 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int t, avg, n; double dp1[15][405], dp2[15][405]; double get(int x) { if

[hdu4714 Tree2cycle]树形DP

题意:给一棵树,删边和加边的代价都为1,求把树变成一个圈所花的最小代价. 思路:对原树进行删边操作,直到将原树分成若干条链,然后通过在链之间添加边形成圈,由于删边和加边一一对应,且最后需要额外一条边连成圈,所以有: 最小代价=(最小链数-1)*2+1=最小链数*2-1. 令dp[i][0]表示i不和i的父亲相连,i这颗子树所形成的最少链数,dp[i][1]表示i和i的父亲相连,i这颗子树所形成的最少链数,则: dp[i][0]=∑dp[j][0]+dp[p][1]-dp[p][0] + dp[q

UVA 10739 String to Palindrome(DP)

In this problem you are asked to convert a string into a palindrome with minimum number of operations. The operations are described below: Here you'd have the ultimate freedom. You are allowed to: Add any character at any position Remove any characte

hdu3480之二维斜率优化DP

Division Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 999999/400000 K (Java/Others) Total Submission(s): 2664    Accepted Submission(s): 1050 Problem Description Little D is really interested in the theorem of sets recently. There's a pro