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 ;
}




UVa 10003 - Cutting Sticks

题目:有一个长l的木头,切成n+1段,切割的代价是当前段长度,求最小代价和。 分析:dp,区间动态规划。石子合并的逆过程。            状态:设F(i,j)为从点i切到j长度的木头切割成对应...
  • mobius_strip
  • mobius_strip
  • 2014年09月15日 10:30
  • 911

UVa 10003Cutting Sticks

这是一道区间dp的经典题目,
  • u014696011
  • u014696011
  • 2014年08月02日 19:50
  • 430

Uva | Cutting Sticks

原题You have to cut a wood stick into pieces. The most affordable company, The Analog Cutting Machiner...
  • u013033845
  • u013033845
  • 2016年08月17日 16:45
  • 506

uva 10003 - Cutting Sticks

刚做这个题的时候,dp(i,j)下疳
  • u010652938
  • u010652938
  • 2014年08月07日 21:04
  • 222

UVA 10003 cutting sticks

典型的区间型DP #include #include #include #include #include using namespace std; #define maxn 50+10 int...
  • Yuta233
  • Yuta233
  • 2018年01月22日 22:59
  • 37

UVA 10003 Cutting sticks

#include #include #include using namespace std; #define maxn 100000 int p[55],dp[55][55]; int m...
  • DoJintian
  • DoJintian
  • 2014年11月09日 22:19
  • 365

UVA - 10003 - Cutting Sticks

原命题链接:PDF/Vjudge 题目的意思是:告诉木棍的总长度,切点个数,和切点位置。每次切割花费的力气为切割的木棍的长度,求出最小花费的力气值。 还没怎么开始看dp,一开始看这道题目,想起了做...
  • TSTNOE
  • TSTNOE
  • 2018年02月06日 22:16
  • 31

UVa:10003 Cutting Sticks

区间DP,1Y。 跟矩阵最优链乘相似。 状态转移方程是dp[i][j]=p[j]-p[i]+min{dp[i][k]+dp[k][j]}(i 三重循环,分别枚举长度起点切点。     #include...
  • kkkwjx
  • kkkwjx
  • 2013年09月01日 09:28
  • 454

UVA - 10003 Cutting Sticks

题意:求最小的代价将木棍剪成n+1根,代价是之后两根的长度,起初我是想如果能知道剪成两端的最小代价,那么我们就可以依次类推下去,最后总代价一定是最小的,但后来发现这是错的,这题并不是贪心,我们不能保证...
  • u011345136
  • u011345136
  • 2013年09月06日 20:19
  • 625

Cutting Sticks UVA - 10003

紫书上面思路已经描述得很清楚了,唯一注意切点下标仅仅相差1的时候是不需要截断的,这个时候要记得将相应的数组元素的值初始化为0,具体实现见如下代码: #include #include #includ...
  • zju2016
  • zju2016
  • 2017年09月13日 20:41
  • 47
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:uva:10003 - Cutting Sticks
举报原因:
原因补充:

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