钢条切割问题-要求输出切割方案-动态规划-C++

问题

钢条切割问题是这样的: 给定⼀段长度为n的钢条和⼀个价格表pi(i=1,2,…n), 求切割钢条⽅案, 使得销售收益最⼤。

注意, 如果长度为n英⼨的钢条的价格pn⾜够⼤, 最优解可能就是完全不需要切割。

输入:钢条的长度n,不同长度钢条的价值Pi,{i=1,…,n}

输出:1、最大收益,2、切割方案。、

输入输出格式如下:

请先在工程目录里建立input.txt文档,因为程序使用txt文档输入来接收数据

输入:

10

1 2 3 4 5 6 7 8 9 10

10

1 1

2 5

3 8

4 9

5 10

6 17

7 17

8 20

9 24

10 24

输入第一行代表输入多少个钢条的数据

第二行是各个钢条长度

第3行代表有多少种钢条单价价格

之后以下各行是对应单价,左列是序号,右列是单价

输出:

代码

#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
#define LEN  100//最大可计算长度
int C[LEN] = { 0 };
int p[LEN] = { 0 };
int cuts[LEN] = { 0 };
int n[LEN] = {0};//输入的钢条长度
int main()
{
	int i, maxk=0;//k记录最大长度
	void fun(int n);
	void printCutSolution( int length);
	int num;//输入多少条钢条长度的数据
	int m;//价格种类
	ifstream fp_read("input.txt");
	ofstream fp_write("output.txt");
	if (fp_read.fail() || fp_write.fail())
	{
		cout << "错误!" << endl;
		exit(0);
	}
	fp_read >> num;
	for (i = 1; i <= num; i++)
	{
		fp_read >> n[i];
		if (n[i] > maxk)
			maxk = n[i];      //后面计算要按最大长度的钢管扩展C[i];
	}
	fp_read >> m; //有多少种价格
	for (i = 1; i <= m; i++)
	{
		fp_read >> maxk;  //接收价格序号,无用
		fp_read >> p[i];
	}
	fun(maxk);
	for (i = 1; i <= num; i++)
	{
		fp_write <<C[n[i]] << endl;
		cout<< C[n[i]] << endl;
		printCutSolution(n[i]);// 输出切割方案
	}
	return 0;
}


void fun(int n)
{
	int i, j,temp;
	for (j = 1; j <= n; j++)
	{
		temp = 0;
		for (i = 1; i <= j; i++)
			if (temp < C[i] + C[j - i])
			{
				temp = C[i] + C[j - i];
				cuts[j] = i;
			}
		C[j] = (temp > p[j]) ? temp : p[j];
		if (C[j] == p[j])
			cuts[j] = j;
	}
}


void printCutSolution(int length)
{
	if (length <= 0)
		return;
	cout << "切割方案: ";

	while (length > 0)
	{
		cout << cuts[length] << " ";
		length -= cuts[length];
	}
	cout << endl;
}

代码分析

设C[j]为长度为j的钢管能切割成所能达到的最大收益,p[j]为长度为j的钢管的单价,容易得出递推公式C[j]=max{p[j],p[i]+C[j-i]}, 采用自底向上的方法,依次从1开始计算出每个长度的钢管的最大收益,即C[j],有2种选择,第一种,它等于当前长度j的单价,即单价就是最大收益,第二种,或者等于切割成i和j-i两部分,等于长度为i的钢管单价加上长度为j-i的钢管的最大收益,这2种选择求最大值即可,显然可以据此推出最优解。

void fun(int n)
{
	int i, j,temp;
	for (j = 1; j <= n; j++)
	{
		temp = 0;
		for (i = 1; i <= j; i++)
			if (temp < C[i] + C[j - i])
			{
				temp = C[i] + C[j - i];
				cuts[j] = i;
			}
		C[j] = (temp > p[j]) ? temp : p[j];
		if (C[j] == p[j])
			cuts[j] = j;
	}
}

在考虑输出最优方案时,在函数fun中,我添加了一个数组cuts,用于保存每个长度对应的切割点位置。在内层循环中,当找到更大的收益时,更新temp、C[j]和cuts[j]的值。

if (C[j] == p[j])
			cuts[j] = j;

看上面2行代码,值得注意的是,如果长度为n英⼨的钢条的价格p[n]⾜够⼤, 最优解可能就是完全不需要切割。故用cuts[]数组记录时,如果j长度的钢条最大收益等于其本身的j长度钢管单价时,将cuts[]更新为该长度j

void printCutSolution(int length)
{
	if (length <= 0)
		return;
	cout << "切割方案: ";

	while (length > 0)
	{
		cout << cuts[length] << " ";
		length -= cuts[length];
	}
	cout << endl;
}

函数printCutSolution接受切割点数组cuts[]和钢条长度length作为参数。它通过回溯方式,根据切割点数组输出切割方案。从长度length开始,不断追溯切割点并输出,直到切割点为0。这样就可以输出最大收益对应的切割方案。

时间复杂度分析

时间复杂度取决于两个嵌套循环的迭代次数。

在 fun 函数中,外层循环迭代次数为 n,内层循环迭代次数取决于当前钢条长度 j,最多为 j 次。因此,fun 函数的时间复杂度为 O(n^2)。

在 printCutSolution 函数中,根据切割方案输出长度和切割点,循环迭代的次数最多为 length 次。因此,printCutSolution 函数的时间复杂度为 O(length)。

综上所述,整个代码的时间复杂度主要由 fun 函数的时间复杂度决定,为 O(n^2)。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值