首页 > 其他分享 >动态规划--图论中使实用场景概述

动态规划--图论中使实用场景概述

时间:2024-05-27 17:32:35浏览次数:26  
标签:图论 parent -- graph 问题 int edge 中使 动态

目录

一 动态规划概述

二 动态规划在图论中应用场景

三 c实例

1. **最短路径问题(Dijkstra算法)**:

2. **最小生成树问题(Kruskal算法)**:


一 动态规划概述

动态规划(Dynamic Programming,简称DP)是一种用于解决具有重叠子问题和最优子结构特性的问题的优化方法。动态规划通过将原问题分解为相互重叠的子问题,并将子问题的解存储在一个表格中,以便在后续计算中重复使用。这种方法可以显著减少计算复杂度,特别是对于具有指数级别复杂度的递归问题。

以下是一个使用动态规划解决的经典问题:0-1背包问题。

问题描述:给定一组物品,每个物品有一定的价值和重量。现在有一个背包,它有一定的承重能力。我们的目标是在不超过背包承重的前提下,将物品放入背包以获得最大的价值。

C实现实例:


#include<stdio.h>
#include <stdlib.h>

int max(int a, int b) {
    return a > b ? a : b;
}

int knapsack(int W, int wt[], int val[], int n) {
    int i, w;
    int **K = (int **)malloc((n + 1) * sizeof(int *));
    for (i = 0; i <= n; i++) {
        K[i] = (int *)malloc((W + 1) * sizeof(int));
    }

    for (i = 0; i <= n; i++) {
        for (w = 0; w <= W; w++) {
            if (i == 0 || w == 0) {
                K[i][w] = 0;
            } else if (wt[i - 1] <= w) {
                K[i][w] = max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]);
            } else {
                K[i][w] = K[i - 1][w];
            }
        }
    }

    int result = K[n][W];

    for (i = 0; i <= n; i++) {
        free(K[i]);
    }
    free(K);

    return result;
}

int main() {
    int val[] = {60, 100, 120};
    int wt[] = {10, 20, 30};
    int W = 50;
    int n = sizeof(val) / sizeof(val[0]);

    printf("最大价值为: %d\n", knapsack(W, wt, val, n));

    return 0;
}

在这个例子中,我们使用动态规划解决了一个0-1背包问题。我们定义了一个二维数组`K`来存储子问题的解。`K[i][w]`表示在前`i`个物品中,背包容量为`w`时能够获得的最大价值。我们根据状态转移方程来填充`K`数组,并在填充过程中利用之前计算的子问题解。最后,`K[n][W]`就是我们要求的最大价值。

这个实现展示了动态规划在解决优化问题中的强大能力。通过将问题分解为子问题并存储子问题的解,我们可以显著减少计算复杂度,从而在有限的时间内找到最优解。

需要注意的是,动态规划适用于具有重叠子问题和最优子结构特性的问题。对于其他类型的问题,可能需要采用其他优化方法或算法。在实际应用中,需要根据问题的具体特点和约束条件来选择合适的算法和数据结构。

二 动态规划在图论中应用场景

动态规划在图论中的许多问题中表现最佳,尤其是在处理具有重叠子问题和最优子结构的问题时。以下是一些具体的应用场景:

1. **最短路径问题**:动态规划可以用来寻找图中两个顶点之间的最短路径。例如,Dijkstra算法和Floyd-Warshall算法都是基于动态规划的求解最短路径问题的方法。

2. **最小生成树问题**:动态规划可以用来寻找无向图的最小生成树,这是一种在网络设计、电路设计等领域中常见的问题。Kruskal算法和Prim算法都是基于动态规划的求解最小生成树问题的方法。

3. **最长公共子序列问题**:在生物信息学中,动态规划可以用来寻找两个序列的最长公共子序列。这个问题可以转换为在图中寻找两个顶点之间的最长路径问题。

4. **背包问题**:动态规划可以用来解决0/1背包问题,即在给定一组物品和一个容量有限的背包的情况下,如何选择物品以使得背包中物品的总价值最大化。这个问题可以转换为在图中寻找一条路径,使得路径上所有顶点的权值之和最大,同时满足路径上顶点的数量限制。

5. **最长递增子序列问题**:在生物信息学中,动态规划可以用来寻找一个序列的最长递增子序列。这个问题可以转换为在图中寻找一条路径,使得路径上所有顶点的值按照一定的顺序递增。

总之,动态规划在图论中的许多问题中都有广泛的应用,它可以帮助我们有效地解决这些问题,找到最优解。

三 c实例

以下是使用C语言实现的一些动态规划在图论中的应用实例:

1. **最短路径问题(Dijkstra算法)**:


#include<stdio.h>
#include<limits.h>

#define INF INT_MAX
#define N 5

int minDistance(int dist[], int sptSet[]) {
    int min = INF, min_index = -1;

    for (int v = 0; v < N; v++) {
        if (sptSet[v] == 0 && dist[v] <= min) {
            min = dist[v];
            min_index = v;
        }
    }

    return min_index;
}

void dijkstra(int graph[N][N], int src) {
    int dist[N];
    int sptSet[N];

    for (int i = 0; i < N; i++) {
        dist[i] = INF;
        sptSet[i] = 0;
    }

    dist[src] = 0;

    for (int count = 0; count < N - 1; count++) {
        int u = minDistance(dist, sptSet);
        sptSet[u] = 1;

        for (int v = 0; v < N; v++) {
            if (!sptSet[v] && graph[u][v] && dist[u] != INF && dist[u] + graph[u][v]< dist[v]) {
                dist[v] = dist[u] + graph[u][v];
            }
        }
    }

    printf("Vertex\tDistance from Source\n");
    for (int i = 0; i < N; i++) {
        printf("%d\t\t%d\n", i, dist[i]);
    }
}

int main() {
    int graph[N][N] = {
        {0, 10, 15, 20, 0},
        {0, 0, 35, 25, 0},
        {0, 0, 0, 30, 0},
        {0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0}
    };

    dijkstra(graph, 0);

    return 0;
}

2. **最小生成树问题(Kruskal算法)**:


#include<stdio.h>
#include<stdlib.h>

#define N 5

typedef struct Edge {
    int src, dest, weight;
} Edge;

typedef struct Graph {
    int V, E;
    Edge* edge;
} Graph;

Graph* createGraph(int V, int E) {
    Graph* graph = (Graph*)malloc(sizeof(Graph));
    graph->V = V;
    graph->E = E;
    graph->edge = (Edge*)malloc(E * sizeof(Edge));
    return graph;
}

int find(int parent[], int i) {
    if (parent[i] == -1)
        return i;
    return find(parent, parent[i]);
}

void union_(int parent[], int x, int y) {
    int xset = find(parent, x);
    int yset = find(parent, y);
    parent[xset] = yset;
}

int isCycle(Graph* graph) {
    int parent[graph->V];
    memset(parent, -1, sizeof(parent));

    for (int i = 0; i< graph->E; i++) {
        int x = find(parent, graph->edge[i].src);
        int y = find(parent, graph->edge[i].dest);

        if (x == y)
            return 1;

        union_(parent, x, y);
    }
    return 0;
}

void kruskal(Graph* graph) {
    int result[graph->V], i, j;
    memset(result, 0, sizeof(result));

    for (i = 0; i< graph->E; i++) {
        int u = graph->edge[i].src;
        int v = graph->edge[i].dest;
        int w = graph->edge[i].weight;

        if (result[u] == 0 && result[v] == 0) {
            result[u] = result[v] = 1;
            printf("Edge %d-%d with weight %d\n", u, v, w);
        }
    }
}

int main() {
    int V = 5;
    int E = 8;
    Graph* graph = createGraph(V, E);

    graph->edge[0].src = 0;
    graph->edge[0].dest = 1;
    graph->edge[0].weight = 10;

    graph->edge[1].src = 0;
    graph->edge[1].dest = 2;
    graph->edge[1].weight = 6;

    graph->edge[2].src = 0;
    graph->edge[2].dest = 3;
    graph->edge[2].weight = 5;

    graph->edge[3].src = 1;
    graph->edge[3].dest = 3;
    graph->edge[3].weight = 15;

    graph->edge[4].src = 2;
    graph->edge[4].dest = 3;
    graph->edge[4].weight = 4;

    graph->edge[5].src = 1;
    graph->edge[5].dest = 2;
    graph->edge[5].weight = 5;

    graph->edge[6].src = 2;
    graph->edge[6].dest = 4;
    graph->edge[6].weight = 2;

    graph->edge[7].src = 3;
    graph->edge[7].dest = 4;
    graph->edge[7].weight = 9;

    if (isCycle(graph))
        printf("Graph contains cycle\n");
    else
        kruskal(graph);

    return 0;
}

这些实例展示了动态规划在解决图论中的最短路径问题和最小生成树问题中的应用。通过使用动态规划,我们可以在较短的时间内找到从源顶点到其他所有顶点的最短路径,以及在无向图中找到最小生成树。这些算法在实际应用中具有广泛的应用价值,例如在网络设计、电路设计、物流优化等领域。需要注意的是,动态规划适用于具有重叠子问题和最优子结构特性的问题。对于其他类型的问题,可能需要采用其他优化方法或算法。在实际应用中,需要根据问题的具体特点和约束条件来选择合适的算法和数据结构。

标签:图论,parent,--,graph,问题,int,edge,中使,动态
From: https://blog.csdn.net/MHD0815/article/details/139146122

相关文章

  • 如何挑选一个合适的HIS系统? 基于B/S架构,JAVA语言,springboot最新技术栈开发的整套云HIS
    如何挑选一个合适的HIS系统?基于B/S架构,JAVA语言,springboot最新技术栈开发的整套云HIS系统源码HIS源码最近有很多人在询问,有没有最优秀的HIS系统?在这里小编是没办法回答的。为什么呢?因为要看你站在什么样的角度,如果是从医院的角度来说,那么我会建议你看看这篇文章,看看什么是......
  • RISC-V 汇编语言--bbci 指令
    bbci 指令是RISC-V汇编语言中的一个条件分支指令,全称为"BranchifBitisClearandIncrement"。该指令会检查指定寄存器中的某一位是否被清除(即为0),如果是,则跳转到指定的标签或地址执行代码。在执行跳转之前,它还会将该位设置为1(即对该位进行“置位”操作)。具体来说,bbci ......
  • 华贝甄选的技术实力,如何成就行业巅峰地位?
    在这个科技日新月异的时代,华贝甄选凭借其卓越的技术实力,在行业中独树一帜,奠定了领先地位。华贝甄选的技术团队汇聚了行业内的精英,他们以专业的知识和丰富的经验,为公司的技术创新提供了坚实的保障。团队不断探索新的技术领域,追求卓越,使得华贝甄选能够始终保持技术的领先性。......
  • 华贝甄选:通证经济生态引领者,数字化时代的引擎!
    在数字经济的浪潮中,华贝甄选科技有限公司凭借其卓越的技术实力和创新精神,成为通证经济领域的翘楚。华贝甄选致力于为客户提供全方位的通证经济解决方案,助力企业实现数字化转型。我们的团队由行业顶尖专家组成,拥有丰富的经验和深厚的技术功底。通证经济,作为数字经济的重要......
  • EBU4201 Introductory Java Programming 2023/24Mini Project(⼉童练习乘法表 下个文
    Task1[25marks]SuperHeroTTisasimpleGraphicalUserInterface(GUI)applicationforchildrenwheretheycanpractisetheirtimestables(seeFigure1).Whenlaunched,yourappshouldlooklikeFigure1-FirstlaunchofSuperHeroTT.Thedrop-downbo......
  • World Creator v2.1.0 解锁版安装教程 (GPU三维地形生成软件)
    前言WorldCreator是一款功能相当强大的地形景观生成器;可以完全根据自己的需求来对地形、景观生成您需要三维模型,内置的大量预设,让您的创建拥有无限的可能性。一、下载地址下载链接:http://dygod/ITSource点击搜索:GPU二、安装步骤1、解压文件,解压后如下2、右键点击......
  • 【数据结构】链式二叉树(超详细)
    文章目录前言二叉树的链式结构二叉树的遍历方式二叉树的深度优先遍历前序遍历(先根遍历)中序遍历(中根遍历)后序遍历(后根遍历)二叉树的广度优先遍历层序遍历二叉树链式结构接口实现二叉树结点个数二叉树叶子结点个数二叉树的深度(高度)二叉树第k层结点个数二叉树查找x......
  • JAVA面试中,面试官最爱问的问题。
     请用wait-notify写一段代码来解决生产者-消费者问题。生产者-消费者问题是一个经典的并发问题,它描述的是两类并发操作的问题:生产者将数据放入缓冲区,消费者从缓冲区取出数据。使用wait()和notify()方法可以在Java中实现这个问题的解决方案。以下是一个简单的示例,其中包含一......
  • react解决电脑分辨率及缩放导致页面变形的问题
    此处借鉴Vue3解决电脑分辨率及缩放导致页面变形的问题-CSDN博客:新建devicePixelRatio.js:/***@description校正windows页面在系统进行缩放后导致页面被放大的问题,通常放大比例是125%、150%***/classDevicePixelRatio{ constructor(){ } //获取系统类型 _get......
  • JAVA面试中,面试官最爱问的问题。
    Java中的final关键字有什么作用?在Java中,final关键字具有多种用途,它可以被应用于类、方法和变量。以下是final关键字的具体作用:修饰变量:当final用于修饰一个变量时,意味着这个变量只能被赋值一次,即它是一个常量。对于基本数据类型,final使变量的值不可变;对于引用类型,final使......