10003 - Cutting Sticks(DP)

类似于最优矩阵链乘,将长区间划分成段区间求解,换句话说:长区间依赖于段区间 。 因此如果利用二重循环递推的话,枚举的顺序应该是木棍的长度从小到大,因为长区间依赖于短区间的最优解 。 所以动态规划的重点我认为就是对状态的定义和动态规划的方向,  状态的定义要确保覆盖所有状态,规划的方向要遵循一个状态依赖于另一个早已解决的状态。     所以该题有两种解决方法:记忆化搜索和递推 。

我分别用这两种方法AC了,记忆化搜索更简单易想,耗时0.339。但是递推更快!耗时0.086 。细节请见代码:

1.记忆化搜索:

#include<bits/stdc++.h>
using namespace std;
const int INF = 2000000000;
int n,l,a[55],d[55][55];
int dp(int i,int j) {
    int& ans = d[i][j];
    if(ans!=-1) return ans;
    ans = INF;
    for(int k=i+1;k<j;k++) {
        ans = min(ans,dp(i,k) + dp(k,j) + a[j] - a[i]);
    }
    return ans;
}
int main() {
    while(~scanf("%d",&l)&&l) {
        scanf("%d",&n);
        memset(d,-1,sizeof(d));//初始化特殊值
        for(int i=0;i<=n;i++) d[i][i+1] = 0; //初始化边界
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        a[n+1] = l; a[0] = 0;
        printf("The minimum cutting is %d.\n",dp(0,n+1));
    }
    return 0;
}

2.递推:

#include<bits/stdc++.h>
using namespace std;
const int INF = 2000000000;
int n,l,a[55],d[55][55];
int main() {
    while(~scanf("%d",&l)&&l) {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        a[n+1] = l; a[0] = 0;
        for(int len=1;len<=n+1;len++) { //按照木棍长度从小到大递推
            for(int i=0;i<=n;i++) {//i + len 就是j
                if(i+len > n+1) break;
                d[i][i+len] = (len == 1 ? 0 : INF);
                for(int k=i+1;k<i+len;k++) { //寻找切割点
                    d[i][i+len] = min(d[i][i+len],d[i][k] + d[k][i+len] + a[i+len] - a[i]);
                }
            }
        }
        printf("The minimum cutting is %d.\n",d[0][n+1]);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 08:31:32

10003 - Cutting Sticks(DP)的相关文章

uva 10003 Cutting Sticks (DP)

uva 10003 Cutting Sticks Description 你的任务是替一家叫Analog Cutting Machinery (ACM)的公司切割木棍.切割木棍的成本是根据木棍的长度而定.而且切割木棍的时候每次只切一段.很显然的,不同切割的顺序会有不同的成本.例如:有一根长10公尺的木棍必须在第2.4.7公尺的地方切割.这个时候就有几种选择了.你可以选择先切2公尺的地方,然后切4公尺的地方,最后切7公尺的地方.这样的选择其成本为:10+8+6=24.因为第一次切时木棍长10公尺,

UVA 10003 Cutting Sticks(区间dp)

Description  Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company, The Analog Cutting Machinery, Inc. (ACM), charges money according to the length of the stick being cut. Their procedure of work requires that they onl

UVA 10003 Cutting Sticks 区间DP+记忆化搜索

UVA 10003 Cutting Sticks+区间DP 纵有疾风起 题目大意 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用 输入输出 第一行是木棍的长度L,第二行是切割点的个数n,接下来的n行是切割点在木棍上的坐标. 输出切割木棍的最小费用 前话-区间dp简单入门 区间dp的入门下面博客写的非常好,我就是看的他们博客学会的,入门简单,以后的应用就得靠自己了. https://blog.csdn.net/qq_41661809/article/d

uva 10003 Cutting Sticks 简单区间dp

// uva 10003 Cutting Sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木棍i-j所需要的最小花费 // 则状态转移为dp(i,j) = min{dp(i,k) + dp(k,j) + a[j]-a[i]) // 其中k>i && k<j // a[j] - a[i] 为第一刀切割的代价 // a[0] = 0,a[n+1] = L; // dp数组初始化的时候dp[i][i+1]的值为 0,这表示 // 每一段都已经是切割了的,不

uva 10003 Cutting Sticks 【区间dp】

题目:uva 10003 Cutting Sticks 题意:给出一根长度 l 的木棍,要截断从某些点,然后截断的花费是当前木棍的长度,求总的最小花费? 分析:典型的区间dp,其实和石子归并是一样的,花费就是石子的和,那么久不用多说了. AC代码: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include <map> #include <

hdu 5623 KK&#39;s Number(dp)

问题描述 我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10?4??)个数,每次KK都会先拿数.每次可以拿任意多个数,直到NN个数被拿完.每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大.在这样的情况下,最终KK的得分减去对手的得分会是多少? 输入描述 第一行一个数T\left( 1\leq T\leq 10\right)T(1≤T≤10),表示数据组

Ural 1353 Milliard Vasya&#39;s Function(DP)

题目地址:Ural 1353 定义dp[i][j],表示当前位数为i位时,各位数和为j的个数. 对于第i位数来说,总可以看成在前i-1位后面加上一个0~9,所以状态转移方程就很容易出来了: dp[i][j]=dp[i][j]+dp[i][j-1]+dp[i][j-2]+.......+dp[i][j-9]: 最后统计即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <

HDU 4908 (杭电 BC #3 1002题)BestCoder Sequence(DP)

题目地址:HDU 4908 这个题是从m开始,分别往前DP和往后DP,如果比m大,就比前面+1,反之-1.这样的话,为0的点就可以与m这个数匹配成一个子串,然后左边和右边的相反数的也可以互相匹配成一个子串,然后互相的乘积最后再加上就行了.因为加入最终两边的互相匹配了,那就说明左右两边一定是偶数个,加上m就一定是奇数个,这奇数个的问题就不用担心了. 代码如下: #include <iostream> #include <stdio.h> #include <string.h&g

Sicily 1146:Lenny&#39;s Lucky Lotto(dp)

题意:给出N,M,问有多少个长度为N的整数序列,满足所有数都在[1,M]内,并且每一个数至少是前一个数的两倍.例如给出N=4, M=10, 则有4个长度为4的整数序列满足条件: [1, 2, 4, 8], [1, 2, 4, 9], [1, 2, 4, 10], [1, 2, 5, 10] 分析:可用动态规划解题,假设dp[i][j],代表满足以整数i为尾数,长度为j的序列的个数(其中每一个数至少是前一个数的两倍).那么对于整数i,dp[i][j] 等于所有dp[k][j-1]的和,其中k满足: