C--动态规划

news/2024/6/16 8:21:29 标签: 动态规划, 算法

动态规划(Dynamic programming,简称 DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

动态规划常常适用于有重叠子问题最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。

通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。

严格意义上,动态规划只能用来解决最优化问题,但在OI中,计数等非最优化问题的递推解法也常被不规范地称作 DP。事实上,动态规划与其它类型的递推的确有很多相似之处,学习时可以注意它们之间的异同。

一、简介

动态规划算法是五种常见的算法之一,通常用于求解具有某种最优性质的问题。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。

动态规划主要用于求解以时间划分阶段的动态过程的优化问题,动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。它往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。

二、适用条件

任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。,适用动态规划的问题必须满足最优化原理和无后效性。

最优化原理,即最优子结构性质,最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。

无后效性,将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。

动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法

三、动态规划算法的设计

动态规划算法的设计主要有两种方法:

(1)自顶向下(又称记忆化搜索、备忘录):基本上对应着递归函数实现,从大范围开始计算,要注意不断保存中间结果,避免重复计算

(2)自底向上(递推):从小范围递推计算到大范围

四、经典例题

动态规划在编程中常用解决最长公共子序列问题、矩阵连乘问题、凸多边形最优三角剖分问题、电路布线等问题。

例题一:最长公共子序列问题(求LCS具体是什么)

给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。

比如两个串为:abcicba 和 abdkscab,则 ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。

Input

第1行:字符串A 

第2行:字符串B 

(A,B的长度 <= 1000)

Output

输出最长的子序列,如果有多个,随意输出1个。

Sample Input

1

2

abcicba

abdkscab

Sample Output

1

abca

思路:此题的切入点就是动态规划,通过动归来确定哪些字符是最长公共子序列中的字符,mat[i][j] 表示第一个序列的前i个字符和第二个序列的前j个字符的公共子序列,动态转移方程为:

 dp[i][j] = max(dp[i-1][j], dp[i][j-1],dp[i-1][j-1] + (A[i]==B[j] ? 1 : 0)),表示在这三种状态中取到最大值,

(1)第一种状态表示不录入第一个序列的第i个字符时的最长公共子序列,

(2)第二种状态表示不录入第二个序列的第j个字符时的最长公共子序列,

(3)第三种状态表示第一个序列的前i-1个字符与第二个序列前j-1个字符的公共子序列加上最后一个字符的录入状态,如果最后的一个字符相等则录入状态为1,否则为0。

然后根据动归的状态,来判断我们要求得的序列中的字符有哪些。

代码如下:

#include<queue>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
  
using namespace std;
  
char a[1001], b[1001];
int dp[1001][1001], len1, len2;
  
void lcs(int i, int j)
{
    for(i=1; i<=len1; i++)
    {
        for(j=1; j<=len2; j++)
        {
            if(a[i-1] == b[j-1])
                dp[i][j] = dp[i-1][j-1] + 1;
            else if(dp[i-1][j] > dp[i][j-1])
                dp[i][j] = dp[i-1][j];
            else
                dp[i][j] = dp[i][j-1];
        }
    }
}
  
void llcs()
{
    int i, j, z = 0;
    char c[1001];
    memset(c, 0, sizeof(c));
    i = len1, j = len2;
    while(i!=0 && j!=0)
    {
        if(a[i-1] == b[j-1])
        {
            c[z++] = a[--i];
            j--;
        }
        else if(dp[i-1][j] < dp[i][j-1])
            j--;
        else if(dp[i][j-1] <= dp[i-1][j])
            i--;
    }
    for(i=z-1; i>=0; i--)
        printf("%c", c[i]);
    printf("\n");
  
}
  
int main()
{
    while(~scanf(" %s", a))
    {
        scanf(" %s", b);
        memset(dp, 0, sizeof(dp));
        len1 = strlen(a);
        len2 = strlen(b);
        lcs(len1, len2);
        llcs();
    }
    return 0;
}

简单案例

0-1背包问题。在这个问题中,给定一组物品,每种物品都有自己的重量和价值,在限定的总重量内,我们如何选择,才能使得物品的总价值最高。每种物品只有一个,可以选择放或不放。

#include <stdio.h>  
#include <stdlib.h>  
  
#define MAX_WEIGHT 100  
#define NUM_ITEMS 5  
  
// 定义物品结构体  
typedef struct {  
    int weight;  
    int value;  
} Item;  
  
// 初始化物品数组  
Item items[NUM_ITEMS] = {  
    {10, 60},  
    {20, 100},  
    {30, 120},  
    {40, 130},  
    {50, 150}  
};  
  
// 动态规划求解0-1背包问题  
int knapsack(int W, Item items[], int n) {  
    int i, w;  
    int K[NUM_ITEMS+1][MAX_WEIGHT+1];  
  
    // 初始化K[][]表  
    for (i = 0; i <= n; i++) {  
        for (w = 0; w <= W; w++) {  
            if (i == 0 || w == 0)  
                K[i][w] = 0;  
            else if (items[i-1].weight <= w)  
                K[i][w] = (items[i-1].value + K[i-1][w-items[i-1].weight] > K[i-1][w]) ?  
                         (items[i-1].value + K[i-1][w-items[i-1].weight]) : K[i-1][w];  
            else  
                K[i][w] = K[i-1][w];  
        }  
    }  
  
    return K[n][W];  
}  
  
int main() {  
    int max_weight = 50; // 背包的最大重量  
    int max_value = knapsack(max_weight, items, NUM_ITEMS); // 计算最大价值  
    printf("The maximum value is %d\n", max_value);  
    return 0;  
}

在这个程序中,我们定义了一个Item结构体来表示物品的重量和价值。knapsack函数通过动态规划求解0-1背包问题,它使用一个二维数组K[][]来存储子问题的解。最后,main函数调用knapsack函数并打印出最大价值。

请注意,这个案例是为了展示动态规划的基本思想,实际应用中可能需要考虑更多的边界条件和优化。


http://www.niftyadmin.cn/n/5439050.html

相关文章

ppt插件构思

功能&#xff1a; 1. 编辑代码 2. 代码运行 3. 代码检查 4. 代码格式化 5. 运行简单的可视化、游戏化、交互式 这是一个针对PPT&#xff08;Microsoft PowerPoint&#xff09;的插件概念描述&#xff0c;该插件旨在提升PPT在演示编程相关内容时的功能丰富度。以下是这个插…

Python 自然语言处理库之stanza使用详解

概要 在自然语言处理(NLP)领域,Python Stanza 库是一个备受推崇的工具,它提供了强大的功能和易用的接口,帮助开发者处理文本数据、进行语言分析和构建NLP应用。本文将深入探讨 Stanza 库的特性、用法,并通过丰富的示例代码展示其在实际项目中的应用。 Stanza 简介 Stan…

LangChain + Qwen(DashScope)

文章目录 引言DashScope API KEY关于 DashScope 和 ModelScope 代码可用模型及费用模型说明计费单价免费额度 引言 常见的 RAG 示例&#xff0c;一般使用 OpenAI&#xff0c;你也可以使用 Qwen 作为 LLM。 在 LangChain 中&#xff0c;调用 Tongyi 来实现。&#xff08;而不是…

汽车研发项目管理数字化平台之工时管理

中国汽车市场连续多年保持千万辆级别的产销量&#xff0c;其规模令人瞩目&#xff0c;市场竞争日趋白热化。车企在新车型研发项目过程中如何控制进度和成本&#xff0c;对车企的发展至关重要。然而&#xff0c;当前很多车企难以全面掌握研发人员在各项目、任务上的工时投入&…

Spring Boot 自动化单元测试类的编写过程

前言 Web环境模拟测试 企业开发不仅要保障业务层与数据层的功能安全有效&#xff0c;也要保障表现层的功能正常。但是我们一般对表现层的测试都是通过postman手工测试的&#xff0c;并没有在打包过程中代码体现表现层功能被测试通过。那么能否在测试用例中对表现层进行功能测…

鸿蒙实战开发:【浏览器制作】

浏览器 介绍 本示例使用[ohos.systemparameter]接口和[Web组件]展示了一个浏览器的基本功能,展示网页&#xff0c;根据页面历史栈前进回退等。 效果预览 首页打开网址 使用说明: 连接Wifi&#xff0c;启动应用&#xff0c;展示默认页面内容;点击默认页面的图标跳转到对应…

预处理 #pragma 命令详解

目录 1.引言 2.#pragma once 3.#pragma waring(...) 4.#pragma comment 4.1.lib 4.2.linker 5.#pragma region … /endregion … 6.#pragma optimize 7.#pragma message (message string) 8.#pragma omp parallel for 9.#pragma pack&#xff08;[ show ] |…

快速搭建一个一元二次方程flask应用

新建flask_service目录、templates子目录 flask_service —— app.py —— templates —— —— index.html app.py from flask import Flask, request, jsonify, render_template import random import matplotlib.pyplot as plt from io import BytesIO import base64app F…