UVA 10003 Cutting Sticks
题意:在给出的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的更多相关文章
- uva 10003 Cutting Sticks 【区间dp】
题目:uva 10003 Cutting Sticks 题意:给出一根长度 l 的木棍,要截断从某些点,然后截断的花费是当前木棍的长度,求总的最小花费? 分析:典型的区间dp,事实上和石子归并是一样的 ...
- UVA 10003 Cutting Sticks 区间DP+记忆化搜索
UVA 10003 Cutting Sticks+区间DP 纵有疾风起 题目大意 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用 输入输出 第一行是木棍的 ...
- uva 10003 Cutting Sticks(区间DP)
题目连接:10003 - Cutting Sticks 题目大意:给出一个长l的木棍, 再给出n个要求切割的点,每次切割的代价是当前木棍的长度, 现在要求输出最小代价. 解题思路:区间DP, 每次查找 ...
- UVA 10003 Cutting Sticks(区间dp)
Description Cutting Sticks You have to cut a wood stick into pieces. The most affordable company ...
- UVa 10003 - Cutting Sticks(区间DP)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 10003 Cutting Sticks 切木棍 dp
题意:把一根木棍按给定的n个点切下去,每次切的花费为切的那段木棍的长度,求最小花费. 这题出在dp入门这边,但是我看完题后有强烈的既是感,这不是以前做过的石子合并的题目变形吗? 题目其实就是把n+1根 ...
- UVA - 10003 Cutting Sticks(切木棍)(dp)
题意:有一根长度为L(L<1000)的棍子,还有n(n < 50)个切割点的位置(按照从小到大排列).你的任务是在这些切割点的位置处把棍子切成n+1部分,使得总切割费用最小.每次切割的费用 ...
- uva 10003 Cutting Sticks (区间dp)
本文出自 http://blog.csdn.net/shuangde800 题目链接: 打开 题目大意 一根长为l的木棍,上面有n个"切点",每个点的位置为c[i] 要按照一 ...
- 10003 Cutting Sticks(区间dp)
Cutting Sticks You have to cut a wood stick into pieces. The most affordable company, The Analog ...
随机推荐
- 相对路径与绝对路径构造file对象
package file; import java.io.File; public class FileTest1 { public static void main(String[] args) { ...
- javascript重点笔记
操作符之间的优先级(高到低):算术操作符 >比较操作符 >逻辑操作符 >"="赋值符号 算术运算符
- C#中ref参数及out参数对比
ref 关键字和out关键字均会导致参数通过引用来传递(相同点1).这是两者的共同点. 通过引用传递参数,会使方法中对参数所做的任何修改都将反映在该变量中. 两者还有一个共同点,那就是:若要使用 re ...
- Eclipse一个打开文件夹目录插件——Open In Explorer
MyEclipse开发的都常用到其中一个"Open In Explorer"的小插件,可以直接在Windows资源管理器中打开选中文件所在的目录,工具虽小,但我们经常需要用到它 由 ...
- soundPool播放短、频、快的声音
package com.example.soundpool; import android.media.AudioManager; import android.media.SoundPool; im ...
- Activity 和 Intent
Activity 和 Intent 一.Intent指向Activity 二.利用 Intent 向第二个 Activity 传数据 三.利用 Intent 接受第二个 Activity 的返回值 四 ...
- 云计算被视为继大型计算机、个人计算机、互联网之后的第4次IT产业革命,顺应了当前各行业整合计算资源和服务能力的要求(转)
云计算被视为继大型计算机.个人计算机.互联网之后的第4次IT产业革命,顺应了当前各行业整合计算资源和服务能力的要求,成为引领当今世界信息技术变革的主力军.越来越多的金融企业认识到只有与云计算结合,才能 ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之坦克的显示
1.先定义坦克的一些属性 class Tank : public CCSprite { public : Tank(); ~Tank(); static Tank* createTankWithTan ...
- C++ 中使用boost::property_tree读取解析ini文件
boost 官网 http://www.boost.org/ 下载页面 http://sourceforge.net/projects/boost/files/boost/1.53.0/ 我下载的是 ...
- JS Call()与Apply()
JS Call()与Apply() ECMAScript规范给所有函数都定义了Call()与apply()两个方法,call与apply的第一个参数都是需要调用的函数对象,在函数体内这个参数就是thi ...