动态规划(2)——常见动态规划模型

\(1.\)数字三角形

每次可以往右下或者左下走一格,求路径的最大权值.

\(d(i,j)=max(d(i+1,j),d(i+1,j+1))+a(i,j).\)边界是\(d(n+1,j)=0\),从下往上推(因为要保证\(i+1\)行在第\(i\)行之前更新)

for(int i=1;i<=n+1;++i) d[n+1][i]=0;
for(int i=n;i>=1;--i)
{
    for(int j=1;j<=i;++j)
    {
        d[i][j]=max(d[i+1][j],d[i+1][j+1])+a[i][j];
    }
}

\(2.\)嵌套矩形

有\(n\)个矩形,每个矩形用一个二元组\((a,b)\)表示。我们规定矩形\(X(a,b)\)可以嵌套在矩形\(Y(c,d)\)中当且仅当\(a<c,b<d\),或者\(b<c,a<d\)(旋转了\(90\)度)。选出尽量多的矩形排成一行 ,使得除了最后一个之外,每个矩形都能嵌套在下一个矩形内。若有多解,保证字典序尽量小

\(DAG\)最长路问题

//dp[i]表示的是从i点出发的最长路
int dp(int x)
{
    int &ans=d[x];
    if(ans) return ans;
    for(int i=1;i<=n;++i)
    {
        if(G[x][i])
        {
            ans=max(ans,dp(i)+1);//注意记录的是从终点到起点的距离,这是为了方便字典序最小方案的输出
        }
    }
    d[x]=ans;
    return ans;
}
void print(int i)
{
    printf("%d ",i);
    for(int j=1;j<=n;++j)
    {
        if(G[i][j]&&d[j]+1==d[i])
        {
            print(j);
        }
    }
}

for(int i=1;i<=n;++i)
{
    scanf("%d%d",&a[i],&b[i]);
    if(a[i]>b[i]) swap(a[i],b[i]);
}
for(int i=1;i<=n;++i)
{
    for(int j=1;j<=n;++j)
    {
        if(a[i]>a[j]&b[i]>b[j])
        {
            G[j][i]=1;
        }
    }
}
int Max=0;
int endpos;
for(int i=1;i<=n;++i)
{
    if(dp(i)>Max)
    {
        Max=dp[i];
        endpos=i;
    }
}
print(endpos);

\(3.\)硬币问题

\[f(i)=min(inf,f[i-Vi]+1|Vi<=i), g(i)=max(-inf,g[i-Vi]+1|Vi<=i) (Vi为硬币的面值)\]

\(4.01\)背包 已有专门专题详细讲解

\(5.\)点集配对问题(状压\(dp\))

\(d(S)\) 表示集合\(S\)配对之后的最短距离

double dis(int i,int j)
{
    return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;++i) scanf("%d%d",&a[i].x,&a[i].y);
    memset(d,0x7f,sizeof(d));
    d[0]=0;
    for(int i=1;i<(1<<n);++i)//由于第一个点无论如何都是要配对的,所以无需枚举(否则时间复杂度会
    {                        //乘上一个n)
        int k=0;
        while(!(i&(1<<k))) ++k;
        for(int j=k+1;j<n;++j)
        {
            if(i&(1<<j)) d[i]=min(d[i],d[i^(1<<k)^(1<<j)]+dis(k,j));
        }
    }
}

\(6.\)最长上升子序列问题\((LIS)\)

初级:\(O(n^2)\) (不过太不优秀了,我学会了第二种,就从没用过它)

进阶:\(O(nlogn)\) \(d[i]\)表示以\(a[i]\)结尾的最长上升子序列的长度

for(int i=1;i<=n;+i) g[i]=inf;
for(int i=0;i<n;++i)
{
    int k=lower_bound(g+1,g+n+1,a[i])-g;
    d[i]=k;
    g[k]=a[i];
}

\(7.\)最长公共子序列问题\((LCS)\)[ 注意:\(LCS\)有时也指最长公共后缀,与\(LCP\)最长公共前缀对应 ]

for(int i=0;i<la;++i)
{
    for(int j=0;j<lb;++j)
    {
        if(a[i]==b[j])
        {
            d[i][j]=max(d[i][j],d[i-1][j-1]+1);
        }
        else if(a[i]!=b[j])
        {
            d[i][j]=max(d[i-1][j],d[i][j-1]);
        }
    }
}

还可以滚动数组优化

int f=0;
for(int i=0;i<la;++i)
{
    f^=1;
    for(int j=0;j<lb;++j)
    {
        if(a[i]==b[j])
        {
            d[f][j]=max(d[f][j],[f^1][j-1]+1);
        }
        else if(a[i]!=b[j])
        {
            d[f][j]=max(d[f^1][j],d[f][j-1]);
        }
    }
}

\(8.\)最大连续和

前缀和做法:

for(int i=1;i<=n;++i)
{
    scanf("%d",&a[i]);
    sum[i]=sum[i-1]+a[i];
}
int Maxn=sum[n],Max=0;
for(int i=n-1;i>=1;--i)
{
    Max=max(Max,Maxn-sum[i]);
    Maxn=max(Maxn,sum[i]);
}

动态规划做法:\(d[i]\)表示以i结尾的最大连续和

for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=n;++i)
{
    d[i]=max(0,d[i-1])+a[i];
}

原文地址:https://www.cnblogs.com/iwillenter-top1/p/11828239.html

时间: 2024-10-29 00:29:00

动态规划(2)——常见动态规划模型的相关文章

【31】常见IO模型浅析 &middot; Qingfeng.Du

note:本文以及<说说Redis的非阻塞IO多路复用技术>都是NIO学习的预热,本文对常见的四种IO模型进行归纳总结. 常见的IO模型有: 同步阻塞IO(Blocking IO):即传统的IO模型 同步非阻塞IO(Non-blocking IO) IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO 异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO 1 同步阻塞IO 简单,就不多说了. 2 同

【动态规划初级】动态规划入门 poj1163 The Triangle

动态规划 我在学习算法的时候,就被动态规划搞得是一头雾水,这几日终于是弄明白是怎么回来. 明白之后我才发觉我以前就碰到过一道ACM题,大意是这样的: 有这样形式的一种排列: 例如: 7      3   8    8   1   0  2   7   4   44   5   2   6   5从顶至下找一条路径,使得这条路径上的数字之和最大,而且每一步只能向左下或右下找,直到到最后一行. 比如:第二行的3只能找第三行8或者1. 上面例子的最大一条路径是:7-3-8-7-5;总和30(原题:ht

nginx源码分析--高性能服务器开发 常见进程模型

1.高性能服务器 对一个高性能服务器来说,处理速度快和资源占用小是典型特性,尤其是当服务器遇到C10K问题的时候(网络服务器在处理数以万计的客户端连接时,往往出现效率低下甚至完全瘫痪,这被称为C10K问题).要做到处理速度足够快,其并发模型的设计相当关键,而要做到资源尤其是内存资源的占用少,就要依赖于其资源分配和资源管理的方案设计. 服务器的并发模型设计是网络编程中很关键的一个部分,服务器的并发量取决于两个因素,一个是提供服务的进程数量,另外一个是每个进程可同时处理的并发连接数量.相应的,服务器

常见IO模型

阻塞IO模型 阻塞IO是最通用的IO,使用这种IO接受数据时,在数据没有到来之前程序会一直等待. 非阻塞IO 当把套接字设置成非阻塞IO时,则对于每次请求,内核都不会阻塞,会立即返回.当没有数据时,会返回一个错误. IO复用 使用IO复用的可以在等待的时候假如超时时间,当超时时间没有到达的时候情况与阻塞IO是一样的,当时间到达,但是没有数据是,系统会自动返回,不在等待.select()函数就是按照一定的时间轮询. 信号驱动IO 信号驱动 信号驱动IO在进程开始时注册一个信号处理的回调函数,进行继

MapReduce 常见SQL模型解析

MapReduce应用场景 前一阵子参加炼数成金的MapReduce培训,培训中的作业例子比较有代表性,用于解释问题再好不过了.有一本国外的有关MR的教材,比较实用,点此下载. MR能解决什么问题?一般来说,用的最多的应该是日志分析,海量数据排序处理.最近一段时间公司用MR来解决大量日志的离线并行分析问题. MapReduce机制 对于不熟悉MR工作原理的同学,推荐大家先去看一篇博文:http://blog.csdn.net/athenaer/article/details/8203990 常用

常见生成式模型与判别式模型

生成式模型 P(X,Y)对联合概率进行建模,从统计的角度表示数据的分布情况,刻画数据是如何生成的,收敛速度快. • 1. 判别式分析 • 2. 朴素贝叶斯Native Bayes • 3. 混合高斯型Gaussians • 4. K近邻KNN • 5. 隐马尔科夫模型HMM • 6. 贝叶斯网络 • 7. sigmoid 信念网 • 8. 马尔科夫随机场Markov random fields • 9. 深度信念网络DBN • 10. 隐含狄利克雷分布简称LDA(Latent Dirichlet

常见设计模型

在开发过程中, 常见的设计模式有十几种. 知道其特点以及使用方法, 对开发的重要程度不言而喻. 以下简要介绍. 常见的设计模式的类型: 一. 创建型 二. 结构型 三. 行为型 其中: 创建型的设计模式有: 1. 单例模式 2. 工厂模式 3. 建造者模式 4. 原型模式 结构型的设计模式有: 1. 适配器模式 2. 修饰器模式 3. 外观模式 4. 享元模式 5. 控制器模式 6. 代理模式 行为型的设计模式有: 1. 责任链模式 2. 命令模式 3. 解释器模式 4. 观察者模式 5. 状态

五类常见算法小记 (递归与分治,动态规划,贪心,回溯,分支界限法)

近日复习了一些算法知识,小记于此 递归与分治法 直接或间接地调用自身的算法称为递归算法. 递归是算法设计与分析中常用的一种技术,描述简单且易于理解. 分治法的设计思想是将一个规模为n难以解决的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同. 递归地解这些子问题,然后将各子问题的解合并得到原问题的解. 典型例子:Fibonacci数列,阶乘,Hanoi塔:二分法搜索.快速排序.合并排序. 动态规划法 动态规划过程是:根据当前(阶段)状态,采取相应的决策,引起状态的转移.如下图,一

【听课记录】17-7-11 动态规划 - 朱全民

此文转载时必须通知博主,并把原文链接及原作者放在正文醒目位置. ————————动态规划初步———————— 一.常见动态规划:求最优解.次优解:统计问题. 二.DP模型:线型- 一条直线.两条直线.多条直线(二维矩阵).树型- 明显能够构成一棵树.多叉树转二叉树:孩子兄弟表示法.图型- 以图为模型.基于连通性的状态压缩DP(哈密顿环).集合类型 三.DP概念:阶段.状态.决策.状态转移.最优化原理.无后效性原理. 四.步骤划分阶段—设置状态—状态转移方程—(优化决策) 五.例题分析 —————