动态规划-带权区间问题

一、动态规划算法的定义:

  为了着手开发一个动态规划算法,我们需要一组从初始问题导出的满足某些基本性质的子问题。

  1. 只存在多项式个子问题
  2. 可以容易的从子问题的解计算出初始问题的解
  3. 在子问题中,从“最小”到“最大”存在一种自然的顺序,与一个容易计算的递推公式相联系。这个递推公式允许我们从某些更小的子问题的解来确定一个子问题的解。

二、带权区间调度问题:

  我们有N个需求,标记为1,2,3,......,N,每个需求指定一个开始时间si,结束时间fi ,每个需求i有一个权值vi,如果两个需求不重叠,那么他们是相容的。

  目标:选择一个两两相容的子集,使得最大。

三、动态规划算法:

  首先让所有的需求按照结束时间非降序排序:f1<=f2.....<fn

  定义p(j) 为使得区间i与j不相交的最大的标记,既i是最右边的在j开始之前的区间。

  设最优解为O,则显然对每个区间都有:

  令区间{1,2,3,......,j}的最优解为OPT(j)

  则:

    OPT(j) = MAX( vj + OPT(p(j)), OPT(j-1))

  并且需求j属于OPT(j),当且仅当:

    OPT(p(j)) + vj >= OPT(j-1)

动态规划算法如下:

  1. 求出所有的OPT(j)

    其中数组M用于存储OPT(j)

    M-Comupte-OPT(j)

     If j == 0 then

      Return 0

     Else if M[j] 不为空 then

      Return M[j]

     Else

      M[j] = MAX( vj + Comupte-OPT(p(j)), Comupte-OPT(j-1))

      Return M[j]

     End

    

  2. 根据上一步求出的OPT[j],求出最优解中包含的区间

   Find-Solution(j)

    If j == 0 then

      Return “”;

    Else

      If  OPT(p(j)) + vj >= OPT(j-1) then

        Return j + Find-Solution(p(j))

      Else

        Return Find-Solution(p(j))

End

     End

原文地址:https://www.cnblogs.com/ordili/p/8497045.html

时间: 2024-10-08 20:46:46

动态规划-带权区间问题的相关文章

POJ 3616 Milking Time 挤奶问题,带权区间DP

题目链接:POJ 3616 Milking Time Milking Time Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4837   Accepted: 2034 Description Bessie is such a hard-working cow. In fact, she is so focused on maximizing her productivity that she decides to sc

HDU 3038 How Many Answers Are Wrong (带权并查集+区间判断)

题意:给你长度为n的区间,m个询问:a,b,c,问这m个问题有多少个是错误的(矛盾). 10 5 1 10 100 7 10 28 1 3 32 4 6 41 6 6 1 由6->6=1,  4->6=41 知4->5=40; 同理 由1->10=100,7->10=28 知1->7=72; 又由1->3=32,4-6=41 知1->7=73,与上面矛盾: 所以答案为1: #include<cstdio> #include<stdlib.h

HDU-3038 How Many Answers Are Wrong(带权并查集区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3038 大致题意: 有一个区间[0,n],然后会给出你m个区间和,每次给出a,b,v,表示区间[a,b]的区间和为v,但每次给出的区间可能与之前的有冲突,问这样起冲突的区间共有多少个 首先区间[a,b]的和可由区间[0,b]的和减去区间[0,a-1]的和得到 但是我们不太可能知道[0,b],故我们只用知道和b的合并过的区间的左端点就行 其实并查集实质就是一颗树,我们可以以树的角度去看待它,理解维护过程 不理解的

并查集练习2(带权并查集)

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~ poj1703 Find them, Catch them (带权并查集) 1 #include<cstdio> 2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 } 10 } 11 int fin(int x){ 12 i

HDU - 3038 How Many Answers Are Wrong (带权并查集)

题意:n个数,m次询问,每次问区间a到b之间的和为s,问有几次冲突 思路:带权并查集的应用,[a, b]和为s,所以a-1与b就可以确定一次关系,通过计算与根的距离可以判断出询问的正确性 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 200010; int f[MAXN],a

bzoj 3065: 带插入区间K小值 替罪羊树 &amp;&amp; AC300

3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1062  Solved: 253[Submit][Status] Description 从 前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一 下,查询区间k小值.他每次向它的随从伏特提出这样的问题: 从左往右第x个到第y个跳蚤中,a[i]第k小的值是多少. 这可难不倒伏特,

hdu3038 How Many Answers Are Wrong【带权并查集】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 题目描述:某个无聊的骚年给他的女友(烧!)一系列三元组x,y,c,表示序列中ax+ax+1+...+ay=c.但是其中有一些是错误的,也就是与前面的信息出现了冲突,比如给了1,2,6和3,4,5接着却给了1,4,100.找出所有错误的三元组的数量 思路:正如一般带权并查集的方法.用par[i]记录父节点,d[i]记录与父节点的差值,如果x与y在不同的集合中则可以自由合并,如果在同一集合中那就有

【带权并查集】【离散化】vijos P1112 小胖的奇偶

每个区间拆成r和l-1两个端点,若之内有偶数个1,则这两个端点对应的前缀的奇偶性必须相同,否则必须相反. 于是可以用带权并查集维护,每个结点储存其与其父节点的奇偶性是否相同,并且在路径压缩以及Union时进行分类讨论即可. 由于n太大,要对两个端点进行离散化. #include<cstdio> #include<algorithm> using namespace std; int fa[10010]; bool rel[10010]; int findroot(int x){ i

带权随机数问题--根据权重随机选择一条路径

最近工作中遇到了一个根据权重随机选择一条路径的问题,一时没有啥好方案,参考借鉴了网上的经验,得出了如下解决方案: 思路:1.求权重的和,对(0,权重之歌和]区间进行划分,每个权重占用长度为权重的区间: 2.产生一个在(0,权重之和]区间的等概率随机数: 3.该随机数落在哪个区间,则该区间对应的权重的映射为本次产生的带权随机数. 1 import java.util.ArrayList; 2 import java.util.HashMap; 3 import java.util.List; 4