uva:10003 - Cutting Sticks

原创 2012年03月31日 08:47:06

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&page=show_problem&problem=944

这个题目开始的时候想正向处理,按照给定的点,不断的划分,但是发现状态转移有些小麻烦,就放弃了那种思路,昨天晚上在睡觉之前突然想到,可以逆向处理的,就是将这支树枝先按照指定的点切割,切割后,在组合起来,看组合的时候能使用的最少费用是多少,这样考虑的时候就最优矩阵链问题相同了,状态转移就很清楚了,动规方程如下:f(i , j) = min{ f(i ,k) , f(k+1 , j) + len(i , j)} 

其中f(i , j) 表示区间[i , j] 的最优值,len(i , j)表示这一区间的长度总和。

代码如下:

#include<iostream>
#include<stdio.h>
#include<string.h>

using namespace std ;

const int INF = 1000000 ;

int num[55][55] ;
int len[55] ;
int n ;
int length ;

int dp(int  , int ) ;
int dist(int , int) ;

int main()
{
//	freopen("in.txt" , "r" , stdin) ;
	while(cin>>length && length)
	{
		int i ;	
		int temp ;
		int k ;

		temp = 0 ;
		scanf("%d" , &n) ;
		//转化为段存储,每一段的长度可以求出
		for(i = 0 ; i < n ; i ++)
		{
			scanf("%d" , &len[i]) ;
			
			k = len[i] ;

			len[i] = len[i] - temp ;
			
			temp = k ;
		}
		len[i] =  length - temp ;

		for(i = 0 ; i <= n ; i ++)
		{
			for(int j = 0 ; j <= n ; j ++)
			{
				num[i][j] = INF ;
			}
		}
		cout<<"The minimum cutting is ";
		cout<<dp(0 , n)<<"."<<endl ;
	}
	return 0 ;
}

int dp(int left , int right)//记忆化搜索
{
	if(left==right)
		return 0 ;

	int & ans = num[left][right] ;

	if(ans < INF)
		return ans ;

	for(int i = left ; i <= right ; i ++)
	{
		if(ans > dp(left , i) + dp(i+1 , right) + dist(left , right) ) 
			ans = dp(left , i) + dp(i+1 ,right) + dist(left , right) ;
	}

	return ans ;
}

int dist(int i , int j)//求这一区间的总和
{
	int sum = 0 ;

	while(i <= j)
	{
		sum += len[i] ;
		i ++ ;
	}

	return sum ;
}

此外需要注意初值要赋为无穷大。

补充采用递推AC的源代码,用递推的时候,要注意阶段的表示,应该以j-i的值递增的顺序来计算。源代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;
const int INF = 1000000 ;

int num[55][55] ;
int len[55] ;
int n ;
int length ;

int dist(int , int );

int main()
{
	//freopen("uva10003.txt" , "r" , stdin) ;

	int i ;
	int j ;
	int k ;
	int temp ;

	while(cin>>length && length)
	{
		temp = 0 ;
		scanf("%d" , &n) ;

		for(i = 0 ; i < n ; i ++)
		{
			scanf("%d" , &len[i]) ;

			k = len[i] ;

			len[i] = len[i] - temp ;

			temp = k ;
		}

		len[i] =  length - temp ;

		for(i = 0 ; i <= n ; i ++)
		{
			for(j = 0 ; j <= n ; j ++)
			{
				if(i!=j)
					num[i][j] = INF ;
				else
					num[i][j] =  0  ;
			}
		}

		for(temp = 0 ; temp <= n ; temp ++)//表示j-i的值,从0到n
		{

			for(i = 0 ; i <= n - temp ; i ++)
			{
				j = i + temp ;

				for(k = 0 ; k <= j ; k ++)
				{
					if(num[i][j] > num[i][k] + num[k+1][j] + dist(i , j))
						num[i][j] = num[i][k] + num[k+1][j] + dist(i , j) ;
				}
			}
		}

		printf("The minimum cutting is %d.\n" , num[0][n]) ;
	}
    return 0;
}

int dist(int i , int j)
{
	int sum = 0 ;

	while(i <= j)
	{
		sum += len[i] ;
		i ++ ;
	}

	return sum ;
}




相关文章推荐

【解题报告】uva10003_Cutting Sticks(切割木棍, dp)

10003 - Cutting Sticks Time limit: 3.000 seconds 题目大意: 有5种面值的硬币...

UVa OJ 10003 - Cutting Sticks

UVa OJ 10003 - Cutting SticksProblemYou have to cut a wood stick into pieces. The most affordable co...

UVa 10003 Cutting Sticks(DP 最优木棍切割)

题意   要把一根长为l的木棍切成n+1段   切割的位置分别为c[1],c[2],...,c[n]   每次切割的成本为当前切割的那一段的长度   如长度100的切成两段成本为100   求完成切割...
  • acvay
  • acvay
  • 2014年08月25日 21:29
  • 675

UVA Problem 10003 Cutting Sticks (切割木棍)

Emma and Eric are moving to their new house they bought after returning from their honeymoon. Fortun...

UVa 10003 - Cutting Sticks(区间DP+记忆化)

给出一个木棒和m个切点,每次切割需要花费等于当前木棒长度的费用。问最小花费。 对整个区间DP然后枚举区间的所有间断点。 转移方程为d[i][j]=min(d[i][k]+d[k][j])。...
  • wcr1996
  • wcr1996
  • 2015年07月25日 14:10
  • 1126

UVa #10003 Cutting Sticks (例题9-9)

9-8还没做完,感觉有点困难。回头再做 这道题很好的训练了最优矩阵连乘。记忆化搜索TLE了,递推则很顺畅。 递推的顺序:不能按照以前的方法递推,因为求某一个区间的解的时候要用到它子...

UVA 10003 Cutting Sticks 切木棍 dp

题意:把一根木棍按给定的n个点切下去,每次切的花费为切的那段木棍的长度,求最小花费。 这题出在dp入门这边,但是我看完题后有强烈的既是感,这不是以前做过的石子合并的题目变形吗? 题目其实就是把n+...
  • hcbbt
  • hcbbt
  • 2013年09月21日 10:29
  • 2613

UVA 10003 Cutting Sticks(区间dp)

题目链接:UVA - 10003 Cutting Sticks题意 给一长度为L的棍子,和n个切割点,每次切割的代价为当前的棍子的长度,问最少的总切割代价是多少。 思路 典型的区间dp ...

uva10003 Cutting Sticks

区间dp
  • sdfzyhx
  • sdfzyhx
  • 2016年10月21日 20:25
  • 138

UVa 10003 - Cutting Sticks

转换思路后,类似矩阵链乘法、石子合并问题。 在长度为l的木棍上分布着n+1个点,依次从0-n+1编号,d[i][j]代表第i个点到第j个点中累加和的最小值。d[i][j] = min( d[i][j...
  • kokosy
  • kokosy
  • 2012年09月18日 13:50
  • 151
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:uva:10003 - Cutting Sticks
举报原因:
原因补充:

(最多只允许输入30个字)