ZCMU—1625

1625: 割木棍

Time Limit: 1 Sec   Memory Limit: 128 MB
[ Submit][ Status][ Web Board]

Description

 给你一根长为 l  的木棍,有 n 标记,每个标记都需要割断,每割一个木棍所需的花费是当前木棍的长度。求最小的花费。

Input

 第一行输入 l ,(l=0时结束)l<=1000

第二行输入一个n ,n<=50

输入n 个数a[i],每个数表示原木棍 a[i] 长度处 有一个标记 0<a[i]<l

Output

 输出最小的花费

Sample Input

100
3
25 50 75
10
4
4 5 7 8
0

Sample Output

The minimum cutting is 200.
The minimum cutting is 22.

【分析】

很明显的dp...不过我怀疑这个数据范围dfs剪枝也可以过....看怎么优化了
这里讲dp...f[i][j]表示从编号i~j的点全部割掉所需要的最小花费,然后类似dijkstra算法...去补齐f[i][j],显然应该从小区间开始,也就是j-i=2开始   然后j-i=3,j-i=4.....直到最后答案,这里可以加个小优化,可以让程序更加简单,就是多加两个点,一个点是0,一个点是l
这样的话f[0][n+1]就是答案
f[i][j]的状态转移也比较容易,f[i][j]=f[i][k]+f[k][j]+a[j]-a[i];  (i<k<j);
(不过后来考虑了一下,发现,其实不需要每次清空状态数组f,每次新的运算只需要f[i][i+1]=0就可以了~算是对这道题目一个更加小的一个优化吧)
【代码】
#include <stdio.h>
#include <string.h>
int a[1000];
int f[100][100];
int main()
{
	int l;
	while (~scanf("%d",&l)&& l)
	{
		memset(f,0,sizeof(f));
		int n;scanf("%d",&n);
		a[0]=0;a[n+1]=l;
		for (int i=1;i<=n;i++) scanf("%d",&a[i]);
		for (int len=2;len<n+2;len++)
		{
			for (int i=0;i<=n-len+1;i++)
			{
				f[i][i+len]=f[i][i+1]+f[i+1][i+len]+a[i+len]-a[i];
				for (int j=i+2;j<i+len;j++)
					if ((f[i][j]+f[j][i+len]+a[i+len]-a[i])<f[i][i+len])
						f[i][i+len]=f[i][j]+f[j][i+len]+a[i+len]-a[i];
			}
		}
		printf("The minimum cutting is %d.\n",f[0][n+1]);
	}
	return 0;	
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值