算法思想经典问题

1、分治法(Divide and Conquer)

思想:将问题分解为若干个子问题,递归地解决子问题,然后将子问题的解 合并 起来得到原问题的解。

经典问题:归并排序(Merge Sort)

cue: 如何将一个无序数组排序?归并排序通过递归地将数组划分为更小的子数组,对子数组进行排序,然后将已排序的子数组合并成一个大的有序数组。

#include <stdio.h>  

// 合并两个有序数组  
void merge(int arr[], int left[], int size_left, int right[], int size_right, int merged[]) {  
    int i = 0, j = 0, k = 0;  

    // 遍历两个数组,将较小的元素放入merged数组中  
    while (i < size_left && j < size_right) {  
        if (left[i] <= right[j]) {  
            merged[k++] = left[i++];  
        } else {  
            merged[k++] = right[j++];  
        }  
    }  

    // 如果有剩余的元素,将它们添加到merged数组的末尾  
    while (i < size_left) {  
        merged[k++] = left[i++];  
    }  

    while (j < size_right) {  
        merged[k++] = right[j++];  
    }  
}  

// 归并排序的主要函数  
void mergeSort(int arr[], int size) {  
    if (size < 2) {  
        return; // 数组只有一个或零个元素时,已经是有序的  
    }  

    // 找到中点,将数组分成两半  
    int mid = size / 2;  

    // 声明两个新数组,用于存储分割后的数组  
    int left[mid];  
    int right[size - mid];  

    // 复制数据到两个新数组  
    for (int i = 0; i < mid; i++) {  
        left[i] = arr[i];  
    }  
    for (int i = mid; i < size; i++) {  
        right[i - mid] = arr[i];  
    }  

    // 对两个新数组进行递归排序  
    mergeSort(left, mid);  
    mergeSort(right, size - mid);  

    // 合并两个已排序的数组  
    int merged[size];  
    merge(arr, left, mid, right, size - mid, merged);  

    // 将合并后的数组复制回原数组  
    for (int i = 0; i < size; i++) {  
        arr[i] = merged[i];  
    }  
}  

// 测试归并排序函数  
int main() {  
    int arr[] = {12, 11, 13, 5, 6, 7};  
    int size = sizeof(arr) / sizeof(arr[0]);  

    printf("Original array: \n");  
    for (int i = 0; i < size; i++) {  
        printf("%d ", arr[i]);  
    }  

    mergeSort(arr, size);  

    printf("\nSorted array: \n");  
    for (int i = 0; i < size; i++) {  
        printf("%d ", arr[i]);  
    }  

    return 0;  
}

2、动态规划(Dynamic Programming)

思想:将问题分解为若干个子问题, 保存 子问题的解以避免重复计算,并利用子问题的解来构建原问题的解。

经典问题:背包问题(Knapsack Problem)

cue: 给定一组物品,每个物品都有自己的重量和价值,以及一个背包的最大承重。如何选择物品放入背包,使得背包内物品的总价值最大,同时不超过背包的承重?

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

#define MAX_N 100 // 假设物品的最大数量为100  
#define MAX_W 1000 // 假设背包的最大容量为1000  

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

// 0-1背包问题的动态规划解法  
int knapsack_01(int W, int n, int weights[], int values[]) {  
    int dp[MAX_W + 1]; // dp[i]表示容量为i的背包能装下的最大价值  
    for (int i = 0; i <= W; i++) {  
        dp[i] = 0; // 初始化dp数组  
    }  

    for (int i = 1; i <= n; i++) { // 遍历每个物品  
        for (int w = W; w >= weights[i - 1]; w--) { // 遍历每个背包容量  
            dp[w] = max(dp[w], dp[w - weights[i - 1]] + values[i - 1]);  
            // 如果装下当前物品后价值更大,则更新dp[w]  
        }  
    }  

    return dp[W]; // 返回背包容量为W时的最大价值  
}  

int main() {  
    int W = 10; // 背包容量  
    int n = 4; // 物品数量  
    int weights[] = {2, 3, 4, 5}; // 物品重量  
    int values[] = {3, 4, 5, 6}; // 物品价值  

    int max_value = knapsack_01(W, n, weights, values);  
    printf("The maximum value in knapsack is: %d\n", max_value);  

    return 0;  
}

3、贪心算法(Greedy Algorithm)

思想:在每一步选择中都采取在当前状态下最好或最优(即最有利 )的选择,从而希望导致结果是全局最好或最优的算法。

经典问题:活动选择问题(Activity Selection Problem)

cue: 给定一系列活动,每个活动都有一个开始时间和结束时间。如何选择尽可能多的活动,使得这些活动在时间上不重叠?

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

// 活动结构体  
typedef struct {  
    int start; // 开始时间  
    int finish; // 结束时间  
} Activity;  

// 比较函数,用于qsort  
int compare(const void *a, const void *b) {  
    Activity *actA = (Activity *)a;  
    Activity *actB = (Activity *)b;  
    return actA->finish - actB->finish; // 按结束时间排序  
}  

// 活动选择函数  
int activitySelection(Activity arr[], int n) {  
    // 首先按结束时间对活动进行排序   排序的作用就是贪心
    qsort(arr, n, sizeof(Activity), compare);  

    int count = 1; // 至少可以选择一个活动  
    int last = 0; // 最后一个被选择的活动索引  

    for (int i = 1; i < n; i++) {  
        // 如果当前活动的开始时间大于或等于上一个被选择活动的结束时间  
        // 则可以选择当前活动  
        if (arr[i].start >= arr[last].finish) {  
            count++;  
            last = i;  
        }  
    }  

    return count;  
}  

int main() {  
    Activity arr[] = {{0, 6},{1, 2}, {3, 4}, {5, 7}, {8, 9}, {5, 9}};  
    int n = sizeof(arr) / sizeof(arr[0]);  

    int max_activities = activitySelection(arr, n);  
    printf("Maximum number of activities that can be selected is: %d\n", max_activities);  

    return 0;  
}

4、回溯法(Backtracking)

思想:通过探索所有可能的候选解来找出所有的解。如果候选解被确认不是一个解(或者至少不是最后一个解),则回溯到上一步尝试其他选择。

经典问题:八皇后问题(N-Queens Problem)

cue: 在N×N的棋盘上放置N个皇后,使得任何两个皇后都不在同一行、同一列或同一对角线上。如何找到所有可能的解决方案?

#include <stdio.h>
int place[8] = {0};                                         // 皇后位置
int flag[8] = {1, 1, 1, 1, 1, 1, 1, 1};                     // 定义列
int d1[15] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; // 定义上对角线(共有15个对角线,
// 因此定义一个长度为15的数组,初值为1代表该对角线没有被皇后占领,
// 若被皇后占领则赋值为0
int d2[15] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; // 定义下对角线
int count = 0;                                              // 记录输出次数
void print()                                                // 定义输出函数
{
    int i, j;
    count++; // 每调用一次输出函数number自加一次,记录摆放方法个数
    printf("No.%2d\n", count);
    int table[8][8] = {0}; // 设置一个8*8的棋盘
    for (i = 0; i < 8; i++)
    {
        table[i][place[i]] = 1; // 将每一行皇后所在位置赋值为1
    }
    for (i = 0; i < 8; i++)
    {
        for (j = 0; j < 8; j++)
        {
            printf("%d|", table[i][j]);
        }
        printf("\n");
    }
}
int queen(int n) // 定义递归回溯函数
{
    int col;
    for (col = 0; col < 8; col++)
    {
        if (flag[col] && d1[n - col + 7] && d2[n + col]) // 判断皇后是否冲突
        {
            place[n] = col; // 放置皇后
            flag[col] = 0;
            d1[n - col + 7] = 0;
            d2[n + col] = 0; // 将该皇后所在的行、列、对角线设置为被占领
            if (n < 7)
            {
                queen(n + 1);
            } // 当行数小于7时;递归调用下一行
            else
            {
                print();
            }              // 调用输出函数
            flag[col] = 1; // 回溯
            d1[n - col + 7] = 1;
            d2[n + col] = 1;
        }
    }
    return count;
}
int main()
{
    count = queen(0);              // 从第0行开始摆放皇后
    printf("共有%d种方法", count); // 输出摆放皇后的方法个数
    return 0;
}

5、分支限界法(Branch and Bound)

思想:类似于回溯法,但使用了剪枝技术来避免搜索一些不可能产生最优解的子空间。

经典问题:旅行商问题(Traveling Salesman Problem,TSP)的近似解

cue: 给定一系列城市和每对城市之间的距离,如何找到一条访问每个城市一次并返回起点的最短可能路线?分支限界法通过限制搜索空间来找到TSP的近似解。

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

#define CITY_COUNT 5 // 假设有5个城市

// 假设的距离矩阵,需要根据你的具体问题来设置
int distance_matrix[CITY_COUNT][CITY_COUNT] = {
    {0, 10, 15, 20, 25},
    {10, 0, 35, 25, 30},
    {15, 35, 0, 30, 35},
    {20, 25, 30, 0, 20},
    {25, 30, 35, 20, 0}};

// 假设的初始和最小成本
int initial_cost = 0;
int min_cost = INT_MAX;

// 路径数组,存储当前路径
int path[CITY_COUNT + 1]; // 多一个位置用于存储起点

// 标记数组,用于跟踪哪些城市已被访问
bool visited[CITY_COUNT] = {false};

// 递归函数来搜索路径
void tsp(int current_city, int current_cost)
{
    // 如果所有城市都已访问过
    if (current_city == CITY_COUNT)
    {
        // 添加起点到终点的距离
        current_cost += distance_matrix[current_city - 1][0];

        // 如果找到了更短的路径,则更新
        if (current_cost < min_cost)
        {
            min_cost = current_cost;
            // 可以在这里打印或存储最短路径
            for (int i = 0; i <= CITY_COUNT; i++)
            {
                printf("%d ", path[i]);
            }
            printf("(%d)\n", current_cost);
        }
        return;
    }

    // 遍历所有未访问的城市
    for (int next_city = 0; next_city < CITY_COUNT; next_city++)
    {
        if (!visited[next_city])
        {
            // 将下一个城市标记为已访问,并添加到路径中
            visited[next_city] = true;
            path[current_city] = next_city;

            // 计算当前路径的成本
            int new_cost = current_cost + distance_matrix[path[current_city - 1]][next_city];

            // 递归地搜索下一个城市
            tsp(current_city + 1, new_cost);

            // 回溯
            visited[next_city] = false;
        }
    }
}

int main()
{
    // 初始化路径的起点
    path[0] = 0;
    visited[0] = true;

    // 开始搜索
    tsp(1, initial_cost);

    printf("Minimum cost: %d\n", min_cost);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/604704.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【SDN:逻辑上集中的控制平面,路由选择算法,LS路由工作过程,距离矢量路由选择(distance vector routing)】

文章目录 SDN&#xff1a;逻辑上集中的控制平面SDN的主要思路SDN控制平面和数据平面分离的优势SDN 架构: 数据平面交换机 路由选择算法路由(route)的概念最优化原则(optimality principle)路由的原则路由算法的分类LS路由工作过程&#xff08;相当于一个上帝&#xff09;链路状…

保护公司机密:避免员工带着数据说拜拜

公司的核心资产之一就是数据。无论是客户信息、研发代码、内部决议、财务报告、商业合同、设计图纸等都是公司的重要资产。如果这些数据在员工离职时被带走&#xff0c;或在员工在职期间不当行为导致数据泄露&#xff0c;将给公司带来重大损失。 然而&#xff0c;保护这些数据…

Ps中 饱和度 和 自然饱和度 的区别?

1.饱和度&#xff08;Saturation&#xff09;&#xff1a;在Photoshop中&#xff0c;饱和度是一个全局性调整&#xff0c;它影响图像中所有颜色的鲜艳程度。当你增加饱和度时&#xff0c;所有的颜色都会变得更浓烈、更鲜艳&#xff1b;相反&#xff0c;减小饱和度会使图像整体变…

暗区突围国际服pc端海外版新手前期如何赚钱 暗区突围新手教学

暗区突围国际服pc端海外版新手前期如何赚钱 暗区突围新手教学 暗区突围是一款极为惊险的射击游戏&#xff0c;让玩家充分感受紧张激烈的战斗以及获取财富的过程。但是有许多新手玩家是不会在游戏里赚钱的&#xff0c;也会在赚钱过程中遇到很多问题&#xff0c;我将在这篇文章…

Learning Continuous Image Representation with Local Implicit Image Function

CVPR2021https://github.com/yinboc/liif 问题引入 图像普遍都是使用像素来表示的&#xff0c;而现实世界是连续的&#xff0c;所以本文借鉴3D中neural implicit representation的思想&#xff0c;以连续的方式表示图像&#xff1b;模型输入坐标值和坐标附近的特征&#xff0…

区块链 | NFT 水印:Review on Watermarking Techniques(一)

&#x1f34d;原文&#xff1a;Review on Watermarking Techniques Aiming Authentication of Digital Image Artistic Works Minted as NFTs into Blockchains 1 应用于 NFT 的水印技术 常见的水印技术类型可以分为&#xff1a; 可见 v i s i b l e \mathsf{visible} visi…

关于Anaconda常用的命令

常用命令 查看当前环境下的环境&#xff1a;conda env list查看当前conda的版本&#xff1b;conda --version conda create -n your_env_name pythonX.X&#xff08;2.7、3.6等)命令创建python版本为X.X。名字为your_env_name的虚拟环境。your_env_name文件可以在Anaconda安装…

2024第16届成都教育连锁加盟展6月1日举办 免费参观

2024第16届成都教育连锁加盟展6月1日举办 免费参观 邀请函 主办单位&#xff1a; 中国西部教体融合博览会组委会 承办单位&#xff1a;重庆港华展览有限公司 博览会主题&#xff1a;责任教育科技兴邦 幼教、普教、高教、校外教育、K12学科辅导、婴幼儿教育、兴趣辅导、学…

STC8增强型单片机开发

1.C51版本Keil环境搭建 下载地址是 Keil Product Downloads 选择C51进行下载&#xff1a; 2.STC环境添加 STC-ISP下载 进入stc官网 深圳国芯人工智能有限公司-工具软件 3.将STC添加到Keil中 打开stc-isp工具 按照图例点击按钮 选择keil的安装目录&#xff0c;以实际安装目…

Nacos单机模式集成MySQL

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Nacos支持三种部署…

VALSE 2024 Workshop报告分享┆ 大规模自动驾驶仿真系统研究

视觉与学习青年学者研讨会&#xff08;VALSE&#xff09;旨在为从事计算机视觉、图像处理、模式识别与机器学习研究的中国青年学者提供一个广泛而深入的学术交流平台。该平台旨在促进国内青年学者的思想交流和学术合作&#xff0c;以期在相关领域做出显著的学术贡献&#xff0c…

五月加仓比特币

作者&#xff1a;Arthur Hayes Co-Founder of 100x. 编译&#xff1a;Liam 编者注&#xff1a;本文略有删减 (以下内容仅代表作者个人观点&#xff0c;不应作为投资决策的依据&#xff0c;也不应被视为参与投资交易的建议或意见&#xff09;。 从四月中旬到现在&#xff0c;当你…

动态规划——路径问题:931.下降路径最小和

文章目录 题目描述算法原理1.状态表示&#xff08;经验题目&#xff09;2.状态转移方程3.初始化4.填表顺序5.返回值 代码实现CJava 题目描述 题目链接&#xff1a;931.下降路径最小和 关于这⼀类题&#xff0c;看过我之前的博客的朋友对于状态表示以及状态转移是⽐较容易分析…

Java 中的 HTTP 客户端库OkHttp、Apache HttpClient和HttpUrlConnection

大家好&#xff0c;我是G探险者。 项目开发里面经常会有这么一种场景&#xff1a;与服务器进行 HTTP 通信。一般存在于服务间远程调用的场景 Java 生态系统提供了多种 HTTP 客户端库&#xff0c;每种都有其自己的特点、优势和适用场景。 本文将介绍几种主要的 Java HTTP 客户…

【练习3】

1.将二叉搜索树转为排序的双向链表 (好久没看数据结构&#xff0c;忘完了&#xff0c;学习大佬的代码&#xff09; class Solution { public:Node* prenullptr,*headnullptr; //pre为每次遍历时的前一个节点&#xff0c;head记录头节点Node* treeToDoublyList(Node* root) {if…

Qt应用开发(拓展篇)——图表 QChart

一、前言 QChart是一个图形库模块&#xff0c;它可以实现不同类型的序列和其他图表相关对象(如图例和轴)的图形表示。要在布局中简单地显示图表&#xff0c;可以使用QChartView来代替QChart。此外&#xff0c;线条、样条、面积和散点序列可以通过使用QPolarChart类表示为极坐标…

Vue3 查看真实请求地址

上回说到Vue2查看真实请求地址&#xff0c;那么Vue3该如何查看呢&#xff1f; 传送门&#xff1a; Vue2 查看真实请求地址 1. bypass函数 使用bypass函数获取代理结果&#xff0c;设置响应头&#xff08;请求头设置未生效&#xff0c;也可以在响应头上看&#xff09;。 2. …

PRL:新型量子传感方案突破纳米测量极限

朴茨茅斯大学的研究人员近期宣布了一项令人振奋的量子传感方案&#xff0c;该方案在测量两个干涉光子之间的横向位移方面达到了前所未有的量子灵敏度。 这一技术的突破为超分辨率成像技术带来了新的可能性。目前&#xff0c;这些技术通常采用单光子源作为探针&#xff0c;用于在…

LCD驱动IC-抗干扰液晶段码显示屏驱动芯片,液晶显示驱动原厂-VK2C23A/B LQFP64/48

产品品牌&#xff1a;永嘉微电/VINKA 产品型号&#xff1a;VK2C23A/B 封装形式&#xff1a;LQFP64/48 概述 VK2C23是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大224点&#xff08;56SEGx4COM&#xff09; 或者最大416点&#xff08;52SEGx8COM&#xff09;的LCD屏。…

电-热耦合市场联合出清!考虑均衡约束的综合能源系统电-热分配方法程序代码!

前言 随着现代城市面临环境问题&#xff0c;原来燃煤的水和空间供暖设备已逐渐被电锅炉和热泵等电气设备所取代。此外&#xff0c;集中生产热能并通过管网分配热能的区域供暖系统&#xff0c;由于其更高的效率&#xff0c;在冬季漫长寒冷的国家和地区越来越受欢迎。供暖设备的…
最新文章