例题9-9 切木棍 UVa10003

1.题目描述:点击打开链接

2.解题思路:本题类似于动态规划中的“最优矩阵链相乘”问题——具有最优子结构。定义d(i,j)表示切割序号为i,j的切点处的小木棒的最优费用。用数组a存储切点的位置,则状态转移方程如下:

d(i,j)=min{d(i,k)+d(k,j)|i<k<j}+a[j]-a[i];

其中,a[j]-a[i]表示切割序号为i到j的小木棒的第一刀的费用。切完后,小木棒变为i~k,k~j两部分。如果设所有切点是1~n,左边界是0,右边界是n+1,那么本题答案是d(0,n+1)。本题的状态有O(N^2)个,每个状态的决策有O(N)个,总时间复杂度为O(N^3)。本题适合用递推写法来计算d(i,j),速度比记忆化写法更快,而且更方便。这里枚举变量是j-i,且要从小到大枚举。因为长区间的结果依赖短区间的结果。

3.代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define INF 1000000
#define maxn 50+10
int L;
int n;
int ans;
int a[maxn];
int d[maxn][maxn];
int main()
{
	//freopen("test.txt", "r", stdin);
	while (scanf("%d", &L) == 1 && L)
	{
		memset(a, 0, sizeof(a));
		memset(d, 1000000, sizeof(d));
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%d", a + i);
		a[0] = 0;
		a[n + 1] = L;
		for (int i = 0; i < n + 1; i++)//计算长度为1的
			d[i][i + 1] = 0;
		for (int i = 0; i < n; i++)//长度为2的
			d[i][i + 2] = a[i + 2] - a[i];
		for (int len = 3; len <= n + 1; len++)//枚举长度
		for (int i = 0; i <= n + 1 - len; i++)
		{
			int j = i + len;
			for (int k = i + 1; k < j; k++)
			{
				int temp;
				temp = d[i][k] + d[k][j] + a[j] - a[i];
				d[i][j] = min(d[i][j], temp);
			}
		}
		printf("The minimum cutting is %d.\n", d[0][n+1]);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值