问题描述:
给定一根长度为 l l l 的钢条 ( l < = 10000 ) (l<=10000) (l<=10000),以及一张价格表,请计算这根钢条能卖出的最大总收益。
价格表表示为 ( l i , p i ) (l_i, p_i) (li,pi), 1 < = i < = k 1<=i<=k 1<=i<=k。
不在价格表中的钢条可卖出价格为 0 0 0。
思路:
根据动态规划的思想,我们可以构建一个数组 d p dp dp,其中 d p [ n ] dp[n] dp[n] 代表了当总钢条长度为 n n n 时所能卖出的最大价值,则递推式显然如下:
d p [ n ] = max 1 < = i < = k ( p i + d p [ n − l i ] ) w h e n n > = l i dp[n] = \max_{1<=i<=k}(p_i + dp[n-l_i]) \quad when \quad n>=l_i dp[n]=1<=i<=kmax(pi+dp[n−li])whenn>=li
d p [ n ] = 0 w h e n n < l i . . . k dp[n] = 0 \quad when \quad n<l_{i...k} dp[n]=0whenn<li...k
而初始化时,只需要将 d p [ 0 , . . . , m i n L e n g t h ] dp[0,\quad ...,\quad minLength] dp[0,...,minLength]设置为 0 0 0即可。
源代码:
//
// main.cpp
// SteelCutting
//
// Created by 胡昱 on 2021/11/11.
//
#include <iostream>
#include <vector>
using namespace std;
class Steel{
public:
int length;
int value;
Steel(int l, int v) {
length = l;
value = v;
}
};
int main() {
// 共m个问题
int m;
cin >> m;
while((m--) > 0) {
// 输入总钢条长度和价格表中不同价格的钢条的数量
int l = 10000, c = 100;
cin >> l >> c;
// 构建动态规划数组
// dp[i]代表了当总钢条长度为i时的最大产出价值
int* dp = new int[l + 1];
// 输入钢条长度价格表(如果长度超出了总钢条长度则不用输入)
vector<Steel> steel;
int length, value, minLength = 2147483647;
for(int i = 0; i < c; ++i) {
cin >> length >> value;
if(length <= l) {
steel.push_back(Steel(length, value));
minLength = min(minLength, length);
}
}
// 如果不能切出任何钢条则直接输出0
if(steel.empty()) {
cout << 0 << endl;
continue;
}
// 进一步初始化动态规划数组
for(int i = 0; i < minLength; ++i) {
dp[i] = 0;
}
// 开始自底向上动态规划
for(int li = minLength; li < l + 1; ++li) {
int tempValue = 0;
for(int i = 0; i < steel.size(); ++i) {
if(steel[i].length <= li) {
tempValue = max(tempValue, steel[i].value + dp[li - steel[i].length]);
}
}
dp[li] = tempValue;
}
cout << dp[l] << endl;
delete [] dp;
}
}
文章评论