由于,这两题有着似乎一样的解法所以将其放在一起总结比較,以达到更好的区分二者的差别所在。

一、区间DP



uva的Cutting Sticks是一道典型的模板题。

题目描写叙述:

有一根长度为l的木棍,木棍上面有m个分割点,每一次分割都要付出当前木棍长度的代价,问如何分割有最小代价。

区间DP的定义:

区间动态规划问题一般都是考虑。对于每段区间,他们的最优值都是由几段更小区间的最优值得到,是分治思想的一种应用。将一个区间问题不断划分为更小的区间直至一个元素组成的区间,枚举他们的组合,求合并后的最优值。

解法:

   设F[i,j](1<=i<=j<=n)表示区间[i,j]内的数字相加的最小代价 。 最小区间F[i,i]=0(一个数字无法合并,∴代价为0)每次用变量k(i<=k<=j-1)将区间分为[i,k]和[k+1,j]两段

区间DP模板,代码:

for(intp = 1 ; p <= n ; p++){      //p是区间的长度,作为阶段
for(int i = 1 ; i <= n ; i++){ //i是穷举区间的起点
int j = i+p-1; //j为区间的终点
for(int k = i ; k < j ; k++)//状态转移
dp[i][j] = min{dp[i][k]+dp[k+1][j]+w[i][j]};//这个是看题目意思,有的是要从k開始不是k+1
dp[i][j]= max{dp[i][k]+dp[k+1][j]+w[i][j]};
}
}

改题解法:

   对于这一题,假设我们仅仅对最左边的分割点到最右边的分割点进行DP。那么得到的答案肯定是错的。由于不是整个区间。所以我们必须在木棍的做左边和左右边分别添加一个点,那么得到的就是整个区间。再对这个区间进行DP求解就可以。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std; const int MAXN = 50 + 10;
const int INF = ~0U >> 2;
int w[MAXN],dp[MAXN][MAXN];
int L,n; int solve(){
n++;
for(int i = 0;i <= n;++i)
for(int j = i+1;j <= n;++j)
dp[i][j] = (i+1 == j ? 0 : INF); w[0] = 0; w[n] = L;
for(int p = 1;p <= n;++p){ //区间长度
for(int s = 0;s <= n-p;++s){ // 起始位置
int e = s + p; //终点
for(int k = s+1;k < e;++k){ //状态转移
dp[s][e] = min(dp[s][e],dp[s][k] + dp[k][e] + w[e] - w[s]);
}
}
}
return dp[0][n];
}
int main()
{
while(scanf("%d",&L),L){
scanf("%d",&n);
for(int i = 1; i <= n; ++i){
scanf("%d",&w[i]);
}
printf("The minimum cutting is %d.\n",solve());
}
return 0;
}

POJ的这题呢,能够看作是上体的上级版。

是没有给出固定的位置的,木板的分割顺序不确定,自由度非常高。这题貌似非常难入手。

可是事实上能够用稍微奇特的贪心来求解。

原理解析:

过程分析是一个涉及了哈夫曼编码的二叉树,由于分析过程有点下复杂。所以自己联想一下吧(囧)。以下给出的算法是不断求解huffman编码中的最小值和次小值。因此,朴素的算法是O(N*N).我们也能够想到用到二叉树结构的优先队列来求解最小值和次小值。此时的时间复杂度减为了O(NlogN).

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std; typedef long long LL;
const int MAXN = 20000 + 10; int N,L[MAXN]; LL solve(){
LL ans = 0; //直到计算到一块木板时为止
while(N > 1){
//寻找最小值,次小值
int mii1 = 0,mii2 = 1;
if(L[mii1] > L[mii2]) swap(mii1,mii2);
for(int i = 2; i < N; ++i){
if(L[i] < L[mii1]){
mii2 = mii1;
mii1 = i;
}
else if(L[i] < L[mii2]){
mii2 = i;
}
}
int t = L[mii1] + L[mii2]; //合并
ans += t; if(mii1 == N-1) swap(mii1,mii2);
L[mii1] = t;
L[mii2] = L[N-1];
N--;
}
return ans;
}
int main()
{
scanf("%d",&N);
for(int i = 0;i < N;++i){
scanf("%d",&L[i]);
}
printf("%lld\n",solve());
return 0;
}

使用STL中的priority_queue实现。

时间复杂度为O(N*logN).

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std; typedef long long LL;
const int MAXN = 20000 + 10; int N,L[MAXN]; LL solve(){
LL ans = 0; priority_queue<int,vector<int>,greater<int> > que;
for(int i = 0;i < N;++i){
que.push(L[i]);
} while(que.size() > 1){
int l1,l2;
l1 = que.top();
que.pop();
l2 = que.top();
que.pop(); ans += l1 + l2;
que.push(l1+l2);
}
return ans;
}
int main()
{
scanf("%d",&N);
for(int i = 0;i < N;++i){
scanf("%d",&L[i]);
}
printf("%lld\n",solve());
return 0;
}

使用手写堆实现。时间复杂度O(N*logN)。

堆实现模板:

//堆的实现
int heap[MAXN << 2],sz = 0 ; void push(int x){
//自己结点的编号
int i = sz++;
while(i > 0){
//父亲结点的编号
int p = (i - 1) >> 1; //假设已经没有大小颠倒则退出
if(heap[p] <= x)break; //把父亲结点的数值放下来。而把自己提上去
heap[i] = heap[p];
i = p;
}
heap[i] = x;
} int pop(){
//最小值
int ret = heap[0]; //要提到根的数值
int x = heap[--sz]; //从根開始向下交换
int i = 0;
while((i << 1 | 1) < sz){
//比較儿子
int a = i << 1 | 1,b = (i << 1) + 2;
if(b < sz && heap[b] < heap[a]) a = b; // 假设没有大小颠倒则退出
if(heap[a] >= x) break; //把儿子提上来
heap[i] = heap[a];
i = a;
} heap[i] = x;
return ret;
}



区间DP与贪心算法的联系(uav Cutting Sticks &amp;&amp; poj Fence Repair(堆的手工实现))的更多相关文章

  1. nyoj891(区间上的贪心)

    题目意思: 给一些闭区间,求最少须要多少点,使得每一个区间至少一个点. http://acm.nyist.net/JudgeOnline/problem.php?pid=891 例子输入 4 1 5 ...

  2. 基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题

    1)区间完全覆盖问题 问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖 样例: 区间长度8,可选的覆盖线段[2,6],[1, ...

  3. 算法提高 矩阵乘法 区间DP

    这是神题,n <= 1000,如果是极限数据普通的n^3区间DP怎么可能过?可偏偏就过了. 刘汝佳大哥的训练指南上面说的存在nlgn的算法解决矩阵链乘问题,可是百度都找不到.... AC代码 # ...

  4. 贪心算法----区间选点问题(POJ1201)

    题目: 题目的大致意思是,给定n个闭区间,并且这个闭区间上的点都是整数,现在要求你使用最少的点来覆盖这些区间并且每个区间的覆盖的点的数量满足输入的要求点覆盖区间的数量. 输入: 第一行输入n,代表n个 ...

  5. 【贪心算法】POJ-1328 区间问题

    一.题目 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, ...

  6. 蓝桥 ADV-232 算法提高 矩阵乘法 【区间DP】

      算法提高 矩阵乘法   时间限制:3.0s   内存限制:256.0MB      问题描述 有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要 ...

  7. 洛谷 P1220 关路灯 (贪心+区间dp)

    这一道题我一直在想时间该怎么算. 看题解发现有个隐藏的贪心. 路径一定是左右扩展的,左右端点最多加+1(我竟然没发现!!) 这个性质非常重要!! 因此这道题用区间dp f[i][j]表示关完i到j的路 ...

  8. 51 nod 石子归并 + v2 + v3(区间dp,区间dp+平行四边形优化,GarsiaWachs算法)

    题意:就是求石子归并. 题解:当范围在100左右是可以之间简单的区间dp,如果范围在1000左右就要考虑用平行四边形优化. 就是多加一个p[i][j]表示在i到j内的取最优解的位置k,注意能使用平行四 ...

  9. 【贪心算法】POJ-2376 区间问题

    一.题目 Description Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cle ...

随机推荐

  1. Python面向对象(成员)(二)

    1. 成员 在类中你能写的所有内容都是类的成员 2. 变量 1. 实例变量: 由对象去访问的变量. class Person: def __init__(self, name, id, gender, ...

  2. centos 装 android studio

    一.安装前的准备 1.1.如果你还没有安装ubuntu 14.04 LTS系统,请参考下面的文章安装 http://blog.csdn.net/lsyz0021/article/details/521 ...

  3. volatile随笔见解

    1.volatile可以保证可见性,不能保证一致性,但是与cas操作结合在实现并发上性能很不错,java并发包下不少类都有这种实现方式. 2.相比synchronized执行成本更低,因为它不会引起线 ...

  4. Python开发:面向对象

    Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的. 如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在 ...

  5. 第五部分 linux系统管理员 开机流程 模组管理 与loader

    第五部分   linux系统管理员  开机流程  模组管理  与loader   开机流程分析 cmos保存电脑硬件的参数 bios 基本的输入输出系统  读取硬件的软件 MBR  master bo ...

  6. c标准库 徐明远 背景基础

    背景基础 1.c语言库用c语言编写   其他语言则不同 早期语言的库是用汇编语言编写的    不同的计算机体系结构有不同的汇编语言   所以在移植性方面差一点   而c语言可以编写出高度可移植性的代码 ...

  7. BNUOJ 6727 Bone Collector

    Bone Collector Time Limit: 1000ms Memory Limit: 32768KB   This problem will be judged on HDU. Origin ...

  8. ubuntu上传项目到github

    https://blog.csdn.net/ajianyingxiaoqinghan/article/details/70544159

  9. UVA - 10591 Happy Number

    Happy Number UVA - 10591 Let the sum of the square of the digits of a positive integer S0 be represe ...

  10. 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛

    Banana Bananas are the favoured food of monkeys. In the forest, there is a Banana Company that provi ...