UVA10003固定点切木棍,怎么切使得每次切之前的木棍长度总和最小

本文介绍了一种经典的动态规划问题——木棍切割问题。通过递推和记忆化搜索两种方法,实现寻找将木棍切割成指定长度段的最经济方案。文章提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题,刚开始想了很久没有想到怎么处理,其实如果想通了很简单的,

用d[begin][end]表示从bigin切点到end切点,这段木棍的最省钱切法,然后就模拟切中间各点,计算交给递归下一层。。。

没有后效性,记忆化搜索,子问题重叠,这三个是dp题目的基本要素。

此题,刚好是一个经典的DP题,当然既可以用递推,也可以用记忆化搜索。

有点像矩阵链乘问题,找到状态转移公式就好了dp[i][j]=max{dp[i][k]+dp[k][j]+len[j]-len[i]|i<k<j};

递推:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#define LL long long
using namespace std;
const int maxn=1e4+10;
const double eps=1e-6;
int l,num;
int main()
{
    while(cin>>l&&l)
    {
        cin>>num;
        int a[55];
        int dp[55][55];
        for(int i=1;i<=num;i++)
            cin>>a[i];
        a[0]=0;
        a[num+1]=l;
        memset(dp,0,sizeof(dp));
        for(int l=2;l<=num+1;l++)
        {
            for(int i=0;i+l<=num+1;i++)
            {
                int j=i+l;
                dp[i][j]=maxn;
                for(int k=i+1;k<j;k++)
                {
                    int cost=dp[i][k]+dp[k][j]+a[j]-a[i];
                    dp[i][j]=min(dp[i][j],cost);
                }
            }
        }
        printf("The minimum cutting is %d.\n",dp[0][num+1]);
    }
    return 0;
}
记忆化搜索:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#define LL long long
using namespace std;
const int maxn=1e4+10;
const double eps=1e-6;
int l,n ,a[55],d[55][55];
int dp(int b,int e)
{
    if(d[b][e]>=0)
        return d[b][e];
    d[b][e]=dp(b,b+1)+dp(b+1,e)+a[e]-a[b];
    for(int i=b+2;i<e;i++)
    {
        int tt=dp(b,i)+dp(i,e)+a[e]-a[b];
        d[b][e]=min(tt,d[b][e]);
    }
    return d[b][e];
}
int main()
{
    while(cin>>l&&l)
    {
        cin>>n;
        for (int i = 0; i <= n + 1; i++)
           for (int j = 0; j <= n + 1; j++)
               if (j - i == 1)
                    d[i][j] = 0;
               else
                   d[i][j] = -1;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        a[0]=0;
        a[n+1]=l;
        printf("The minimum cutting is %d.\n",dp(0,n+1));
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值