钢管切割问题

问题重现

在钢管切割的背景下,已经知道长度为1−n的钢管的价值,给定长度为n的钢管在切割若干次(也可以不切割)所带来的最小价值(最大价值)是?

问题分析

钢管切割问题大家都不陌生,这里就不具体举出某个例子了。具体的思路就是用dp[i]记录当总长度为i时的最小(最大)价值,即
dp[i] = min{p[i] + dp[i - j]}(j : 1 ➡ i)

代码

int bottm_up_cut_rod(int p[],int n){
    int q;
    for(int j = 1;j <= n;j++){
        q = mx;
        for(int i = 1;i <= j;i++){
            q = min(q,p[i] + dp[j - i]);
        }
        dp[j] = q;
    }
    return dp[n];
}

注意

根据题目要求最大还是最小值,在以下两点会有区别

  1. 临时变量q的初始化,若求最大则初始化为-1,若求最小则初始化为一个超大的数
  2. dp数组的初始化,对于下标从1➡n的元素均按照上述方式初始化

换一种思路(钢管切割问题➡另类背包问题)

具体转化如下:
起始长度 ➡ 背包容量、物品种数
钢管每段长度 ➡ 物品重量
价值 ➡ 价值
同时是完全背包问题,因为每种长度的切割可以无限制,再同时,由于每段长度求和必等于原始长度,由此,这是一个要求装满的完全背包问题,贴上代码:

#include <iostream>
#include <cstdio>
#define maxn 1010
#define inf 9999999
using namespace std;

int dp[maxn],v[maxn],w[maxn];
int n;
void complete_pack(int vi,int wi){
    for(int i = vi; i <= n; i++)//正序
        dp[i] = min(dp[i],dp[i - vi] + wi);
}

void init(){
    dp[0] = 0;
    for(int i = 1;i < maxn;i++){
        dp[i] = inf;
    }
}

int main()
{
    while(~scanf("%d",&n)){
        init();
        for(int i = 1;i <= n;i++){
            v[i] = i;
            scanf("%d", &w[i]);
        }
        for(int i = 1;i <= n;i++){
            complete_pack(v[i],w[i]);
        }
        printf("%d\n", dp[n]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值