题意:在给出的n个结点处切断木棍,并且在切断木棍时木棍有多长就花费多长的代价,将所有结点切断,并且使代价最小。

思路:设DP[i][j]为,从i,j点切开的木材,完成切割需要的cost,显然对于所有DP[i][i+1]=0,记w[i][j]为从i,j点切开的木材的长度,因此可以枚举切割点,dp[i][j]=min(dp[i][k]+dp[k][j])+w[i][j],k就是枚举的切割点.

AC代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int SIZEN=;
const int INF=<<;
int x[SIZEN];
int dp[SIZEN][SIZEN];
int w[SIZEN][SIZEN];
void init()
{
memset(dp,-,sizeof(dp));
}
int dfs(int l,int r)
{
if(dp[l][r]!=-)
return dp[l][r];
int ans=INF;
for(int i=l+; i<r; i++)
{
ans=min(ans,dfs(l,i)+dfs(i,r));
}
dp[l][r]=ans+w[l][r];
return dp[l][r];
}
void solve(int len)
{
int n;
scanf("%d",&n);
init();
for(int i=; i<=n; i++)
scanf("%d",&x[i]);
x[]=;
x[n+]=len;
for(int i=; i<=n; i++)
for(int j=i; j<=n+; j++)
w[i][j]=x[j]-x[i];
for(int i=; i<=n; i++)
dp[i][i+]=;
int ans=dfs(,n+);
printf("The minimum cutting is %d.\n",ans);
}
int main()
{
int len;
while(scanf("%d",&len)!=EOF&&len)
solve(len);
}

这道题涉及到一个知识点:区间DP:(转自calmound)

区间动态规划问题一般都是考虑,对于每段区间,他们的最优值都是由几段更小区间的最优值得到,是分治思想的一种应用,将一个区间问题不断划分为更小的区间直至一个元素组成的区间,枚举他们的组合 ,求合并后的最优值。
设F[i,j](1<=i<=j<=n)表示区间[i,j]内的数字相加的最小代价
最小区间F[i,i]=0(一个数字无法合并,∴代价为0)

每次用变量k(i<=k<=j-1)将区间分为[i,k]和[k+1,j]两段
For p:=1 to n do // p是区间长度,作为阶段。 
for i:=1 to n do // i是穷举的区间的起点
begin
j:=i+p-1; // j是 区间的终点,这样所有的区间就穷举完毕
if j>n then break; // 这个if很关键。
for k:= i to j-1 do // 状态转移,去推出 f[i,j]
f[i , j]= max{f[ i,k]+ f[k+1,j]+ w[i,j] } 
end; 
这个结构必须记好,这是区间动态规划的代码结构。

下面是关于该题的一个优化代码(四边形优化),我还没搞懂,先贴出来吧:

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int SIZEN=;
const int INF=<<;
int x[SIZEN];
int dp[SIZEN][SIZEN];
int w[SIZEN][SIZEN];
int s[SIZEN][SIZEN];
//dp[i][j]=min(dp[i][k]+dp[k][j])+w[i][j]
void init(){
memset(dp,-,sizeof(dp));
}
void work(int n){
for(int i=;i<=n;i++) dp[i][i+]=;
for(int i=;i<=n;i++) s[i][i+]=i;
for(int l=;l<=n+;l++){
for(int i=;i+l-<=n+;i++){
int j=i+l-;
dp[i][j]=INF;
for(int k=s[i][j-];k<=s[i+][j];k++){
int tmp=dp[i][k]+dp[k][j];
if(dp[i][j]>tmp){
dp[i][j]=tmp;
s[i][j]=k;
}
}
dp[i][j]+=w[i][j];
}
}
}
void solve(int len){
int n;
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&x[i]);
x[]=;x[n+]=len;
for(int i=;i<=n;i++)
for(int j=i;j<=n+;j++)
w[i][j]=x[j]-x[i];
work(n);
/*for(int i=0;i<=n+1;i++){
for(int j=i+1;j<=n+1;j++) printf("%d ",dp[i][j]);
printf("\n");
}
for(int i=0;i<=n+1;i++){
for(int j=i+1;j<=n+1;j++)
printf("%d ",s[i][j]);
printf("\n");
}*/
printf("The minimum cutting is %d.\n",dp[][n+]);
}
int main()
{
int len;
while(scanf("%d",&len)!=EOF&&len)
solve(len);
}

本篇博文并非出自本人之手,只是做个总结,感谢ACalvin男神的帮助。

UVA 10003 Cutting Sticks的更多相关文章

  1. uva 10003 Cutting Sticks 【区间dp】

    题目:uva 10003 Cutting Sticks 题意:给出一根长度 l 的木棍,要截断从某些点,然后截断的花费是当前木棍的长度,求总的最小花费? 分析:典型的区间dp,事实上和石子归并是一样的 ...

  2. UVA 10003 Cutting Sticks 区间DP+记忆化搜索

    UVA 10003 Cutting Sticks+区间DP 纵有疾风起 题目大意 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用 输入输出 第一行是木棍的 ...

  3. uva 10003 Cutting Sticks(区间DP)

    题目连接:10003 - Cutting Sticks 题目大意:给出一个长l的木棍, 再给出n个要求切割的点,每次切割的代价是当前木棍的长度, 现在要求输出最小代价. 解题思路:区间DP, 每次查找 ...

  4. UVA 10003 Cutting Sticks(区间dp)

    Description    Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company ...

  5. UVa 10003 - Cutting Sticks(区间DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  6. UVA 10003 Cutting Sticks 切木棍 dp

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

  7. UVA - 10003 Cutting Sticks(切木棍)(dp)

    题意:有一根长度为L(L<1000)的棍子,还有n(n < 50)个切割点的位置(按照从小到大排列).你的任务是在这些切割点的位置处把棍子切成n+1部分,使得总切割费用最小.每次切割的费用 ...

  8. uva 10003 Cutting Sticks (区间dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接:  打开 题目大意 一根长为l的木棍,上面有n个"切点",每个点的位置为c[i] 要按照一 ...

  9. 10003 Cutting Sticks(区间dp)

      Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company, The Analog ...

随机推荐

  1. c++ 中CImage类Load函数,路径中含有空格应对策略!

    最近,在写一些东西的时候,需要用到CImage类将JPG各式的图片转换成BMP图片,传入的是图片的绝对地址:如C:\Users\Administrator\Documents\Visual Studi ...

  2. 关于Linux系统清理/tmp/文件夹的原理

    转自:http://www.opsers.org/base/clean-up-on-the-linux-system-tmp-folder-you-may-want-to-know.html 我们知道 ...

  3. 基于visual Studio2013解决算法导论之011快排改良

     题目 快排改良 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #in ...

  4. 利用FFT 计算生成离散解析信号

    通常我们用到的信号都是实值信号,但是我们可以根据这个实信号构造出一个复信号,使得这个复信号只包含正频率部分,而且这个复信号的实部正好就是我们原来的实值信号.简单的推导可知,复信号的虚部是原信号的希尔伯 ...

  5. Single Image Haze Removal Using Dark Channel Prior翻译

    这段时间在回顾以前做的去雾,顺便就把这篇文章翻译了一下,看看有没有同行交流.由于是用LaTex排版的,所以只能转为图片传上来了.另外,英语水平有限,大部分都是靠词典,所以只能勉强着看了.

  6. golang各版本的变化

    https://golang.org/doc/https://golang.org/doc/go1.6https://golang.org/doc/go1.5https://golang.org/do ...

  7. 性能测试之LoardRunner 结果分析

    性能结果分析是性能测试中的重中之重,也是难点所在,以下总结了看图的一些顺序: 1.首先可以检查Analysis模块提供的Summary Report,整个测试过程中我们所关心的各业务 2.首先关注性能 ...

  8. Visio中添加、移动或删除形状上的连接点的方法

    Visio中添加.移动或删除形状上的连接点的方法 利用Visio画图时,学会使用连接点能使你的画图质量和速度大幅度提高.下面在Visio2010中,以一个例子讲述如何使用连接点. 一. 准备 1. 打 ...

  9. 通过cl_dd_document来实现在ALV中输出标题头

    *&---------------------------------------------------------------------* *& Report ZTEST_LIN ...

  10. 手机SIM卡无法识别解决方案

    SIM卡是工作中测试用的,经常插拔到不同的手机,前两天SIM卡放到手机中都能正常识别,今天插入到另一款手机中发现无法识别.心里糟了,是不是卡坏了,根据之 前的直觉,在公司找了一块橡皮,在SIM卡的芯片 ...