DP求钢管切法的最小代价(XJTU算法实验二)

该博客介绍了一个解决如何在给定的钢条上按指定位置切割以最小化总代价的算法。通过动态规划实现,利用了最优子结构,时间复杂度为O(n^2)。代码展示了如何用C++实现这一算法,并给出了一个示例输入和输出。

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

设有一个长度为L的钢条,在钢条上标有n个位置点(p1,p2,…,pn)。现在需要按钢条上标注的位置将钢条切割为n+1段。假定每次切割所需要的代价与所切割的钢条长度成正比。请编写一个算法,能够确定一个切割方法,使切割的总代价最小。
输入:
7 4
5 4 3 1
结果:
16

思路

先定义一维数组p[ n+1 ],其中p[i]是第i个切割点的位置(注意p应为有序的)。特别地,p[ 0 ]=0,p[ n+1 ]=L。

用a[ i ][ j ]记录从第i个切割点到第j个切割点的最小代价。其最优子结构的递归关系为:

j - i =1时,a[ i ][ j ] = 0;

j - i =2时,a[ i ][ j ] = p[ j ] - p[ i ];

3 ≤ j - i 时,a[ i ][ j ] = min{ p[ j ] - p[ i ] +a[ i ][ k ] +a[ k ][ j ] },i+1 ≤ k ≤ j-1。

最后a[ 0 ][ n+1 ]即为所求。时间复杂度为O(n^2)。

代码

#include<iostream>
using namespace std;

void bubbleSort(int *p, int n)
{
	for(int i=1;i<n+1;i++){
		for(int j=1;j<n-i+1;j++){
			if(p[j+1]<p[j]){
				int temp = p[j];
				p[j] = p[j+1];
				p[j+1] = temp;
			}
		}
	}
}

int min(int a, int b)
{
		return a<b?a:b;;
}

int Solution(int begin, int end, int *p, int **a)
{ 
	if(end-begin==1)
		return 0;
	else if(end-begin==2)
		return p[end]-p[begin];
	else{
		int least=a[begin][begin+1]+a[begin+1][end]+p[end]-p[begin];
		for(int i=2;i<end-begin;i++){
			least = min(least, a[begin][begin+i]+a[begin+i][end]+p[end]-p[begin]);
		}
		return least;
	}
} 

int main()
{ 
	int L, n;
	cin>>L>>n;
	int *p;
	p = new int[n+2];
	p[0] = 0;
	for(int i=1;i<n+1;i++){
		cin>>p[i];
	}
	bubbleSort(p, n);
	p[n+1] = L;
	int **a = new int*[n+2];//创建二维数组记录最小代价值
	for(int i=0;i<n+2;i++){
		a[i] = new int[n+2];
	}
	for(int i=1;i<n+2;i++){
		for(int j=0;j<n+2-i;j++){
			a[j][i+j] = Solution(j,i+j,p,a);
		}
	}
	cout<<Solution(0,n+1,p,a);
	return 0;
}

运行示例

在这里插入图片描述

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值