【九十四】【算法分析与设计】练习四蛮力法练习,排列问题和组合问题,求解最大连续子序列和问题,求解幂集问题,求解0/1背包问题,求解任务分配问题

求解最大连续子序列和问题

给定一个有n(n≥1)个整数的序列,要求求出其中最大连续子序列的和。

例如:

序列(-2,11,-4,13,-5,-2)的最大子序列和为20

序列(-6,2,4,-7,5,3,2,-1,6,-9,10,-2)的最大子序列和为16。

规定一个序列最大连续子序列和至少是0(看成0个元素构成的子序列),如果小于0,其结果为0。

1.

子数组累加和最大值问题,如何划分问题,子数组应该如何划分?

可以划分为以某一个位置结尾的子数组,以i位置结尾的子数组.

所有的子数组被划分成以0下标结尾的子数组,以1下标结尾的子数组.......

我们只需要解决每一个划分出来的子数组集合对应的问题即可.

也就是解决以某一个位置结尾的子数组累加和最大值是多少.

2.

以i位置结尾的子数组可以划分成两种,第一种是只包含i位置元素,第二种是不只包含i位置元素.

只包含i位置元素的累加和最大值为arr[i],不只包含i位置元素的累加和最大值为arr[i]+(以i-1位置结尾的子数组累加和最大值).

我们要求最大值,所以以i位置结尾的子数组累加和最大值为max(arr[i],arr[i]+(以i-1位置结尾的子数组累加和最大值)).

3.

动态规划,自底向上的动态规划和自顶向下的动态规划.

自底向上的动态规划写法

 
#include<bits/stdc++.h> // 导入标准库头文件
using namespace std; // 使用标准命名空间
#define int long long // 将int类型定义为long long类型,便于处理大数
#define endl '\n' // 将endl定义为换行符

// 定义两个测试用的数组
vector<int>arr1 = { -2,11,-4,13,-5,-2 };
vector<int>arr2 = { -6,2,4,-7,5,3,2,-1,6,-9,10,-2 };

// 定义一个动态规划数组和一个存储当前数组的变量
vector<int>dp;
vector<int>arr;
// 定义存储最大子数组和的变量
int ret;

// 初始化函数
void init() {
        dp.assign(arr.size(), 0); // 将dp数组初始化为和当前数组相同大小,并赋初值为0
        ret = 0; // 将ret初始化为0
}

// 求解最大子数组和的函数
void solve() {
        for (int i = 0; i < arr.size(); i++) { // 遍历数组中的每一个元素
                dp[i] = max((i - 1 >= 0 ? dp[i - 1] : 0) + arr[i], arr[i]); // 计算以当前位置结尾的最大子数组和
                ret = max(ret, dp[i]); // 更新最大子数组和
        }
        cout << ret << endl; // 输出结果
}

// 测试函数
void f() {
        arr = arr1; // 将数组设置为arr1
        init(); // 初始化
        solve(); // 求解

        arr = arr2; // 将数组设置为arr2
        init(); // 初始化
        solve(); // 求解
}

// 主函数
signed main() {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 提高输入输出效率
        f(); // 调用测试函数
}

自顶向下的动态规划写法(记忆化递归)

 
#include<bits/stdc++.h> // 导入标准库头文件
using namespace std; // 使用标准命名空间
#define int long long // 将int类型定义为long long类型,便于处理大数
#define endl '\n' // 将endl定义为换行符

// 定义两个测试用的数组
vector<int>arr1 = { -2,11,-4,13,-5,-2 };
vector<int>arr2 = { -6,2,4,-7,5,3,2,-1,6,-9,10,-2 };

// 定义一个当前数组的变量和一个存储最大子数组和的变量
vector<int>arr;
int ret;

// 定义一个动态规划数组
vector<int>dp;

// 记忆化递归函数,求以位置i结尾的最大子数组和
int dfs(int i) {
        if (dp[i] != -1) return dp[i]; // 如果dp[i]已被计算,则直接返回dp[i]
        if (i - 1 < 0) { // 如果i是第一个元素
                dp[i] = arr[i]; // 直接返回arr[i]
                return dp[i]; // 返回dp[i]
        }
        dp[i] = max(dfs(i - 1) + arr[i], arr[i]); // 计算dp[i],取包含i的子数组和与仅包含i元素的子数组和的最大值
        ret = max(ret, dp[i]); // 更新最大子数组和
        return dp[i]; // 返回dp[i]
}

// 初始化函数
void init() {
        ret = 0; // 将ret初始化为0
        dp.assign(arr.size(), -1); // 将dp数组初始化为和当前数组相同大小,并赋初值为-1
}

// 求解最大子数组和的函数
void solve() {
        for (int i = 0; i < dp.size(); i++) dfs(i); // 遍历数组中的每一个元素,调用dfs函数
        cout << ret << endl; // 输出结果
}

// 测试函数
void f() {
        arr = arr1; // 将数组设置为arr1
        init(); // 初始化
        solve(); // 求解

        arr = arr2; // 将数组设置为arr2
        init(); // 初始化
        solve(); // 求解
}

// 主函数
signed main() {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 提高输入输出效率
        f(); // 调用测试函数
}

求解幂集问题

对于给定的正整数3,求1~3构成的集合的所有子集(幂集)。

{}

{1}

{2}

{1,2}

{3}

{1,3}

{2,3}

{1,2,3}

1.

组合问题,有3个整数,选出其中的部分整数作为一个集合,所有不同的情况都列出来.

对于任意的整数,在选出来的集合中,都可以选择或者不选择两种方案.

所以一共有2^3种方案.对于数字1可以选择或者不选择,对于数字2可以选择或者不选择,对于数字3可以选择或者不选择.

一共有2*2*2=2^3种方案数.

2.

在每一种方案中对于每一个数字,都有对应的选择,选择或者不选择,因此可以用1表示选择0表示不选择.

例如空集对应000,{1}对应100,{2}对应010,{1,2}对应110....{1,2,3}对应111.

如果000~111全部是二进制数,那么对应的十进制数是0~2^3-1.

每一个数的二进制都对应一种方案.

3.

对于每一种方案,只需要提取对于二进制数所有位置的1就知道选择了哪些元素.

 
#include<bits/stdc++.h> // 导入标准库头文件
using namespace std; // 使用标准命名空间
#define int long long // 将int类型定义为long long类型,便于处理大数
#define endl '\n' // 将endl定义为换行符

// 定义一个包含1,2,3的数组
vector<int> arr = { 1,2,3 };
// 定义一个变量n来存储幂集的大小
int n;

// 初始化函数
void init() {
        n = pow(2, arr.size()); // 计算幂集的大小,即2的arr.size()次幂
}

// 求解幂集的函数
void solve() {
        for (int i = 0; i < n; i++) { // 遍历从0到2^arr.size() - 1的所有整数
                cout << "{ "; // 输出子集的左花括号
                for (int j = 0; j < arr.size(); j++) { // 遍历数组中的每一个元素
                        if (i & (1 << j)) { // 检查整数i的第j位是否为1
                                cout << arr[j] << " "; // 如果是,则输出对应的数组元素
                        }
                }
                cout << "}" << endl; // 输出子集的右花括号和换行符
        }
}

// 主函数
signed main() {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 提高输入输出效率
        init(); // 初始化
        solve(); // 求解幂集
}

求解0/1背包问题

有n个重量分别为{w1,w2,…,wn}的物品,它们的价值分别为{v1,v2,…,vn},给定一个容量为W的背包。设计从这些物品中选取一部分物品放入该背包的方案,每个物品要么选中要么不选中,要求选中的物品不仅能够放到背包中,而且具有最大的价值。

并对下表所示的4个物品求出W=6时的所有解和最佳解。

物品编号

重量

价值

1

5

4

2

3

4

3

2

3

4

1

1

1.

0/1背包问题也是组合问题.有n个物品,选择一部分物品出来放到一个集合里面.

2.

一共有4个物品,每一个物品对应一个二进制数,一共是四个位置的二进制数,0~2^4-1.

每一个数对应一种选择方案,要么选择要么不选择.

一共有2^4种方案数.

3.

printf输入格式很方便,但是要注意string转化为c_str().

 
#include<bits/stdc++.h> // 导入标准库头文件
using namespace std; // 使用标准命名空间
#define int long long // 将int类型定义为long long类型,便于处理大数
#define endl '\n' // 将endl定义为换行符

// 定义一个结构体node,用来存储物品的重量和价值
struct node {
        int weight; // 物品重量
        int value; // 物品价值
};

// 定义变量n表示物品数量,nsize表示所有可能选择方案的数量,maxWeight表示背包的最大承重
int n = 0;
int nsize = 0;
int maxWeight = 6; // 背包最大承重为6

// 定义一个包含4个物品的数组,每个物品包含重量和价值
vector<node> arr = { {5,4},{3,4},{2,3},{1,1} };

// 定义一个结构体node1,用来存储选择方案的字符串表示、总重量和总价值
struct node1 {
        string str = ""; // 选择方案的字符串表示
        int weight = 0; // 选择方案的总重量
        int value = 0; // 选择方案的总价值
};

// 定义一个变量ret,用来存储最佳选择方案
node1 ret;

// 初始化函数
void init() {
        n = 4; // 物品数量为4
        nsize = pow(2, n); // 所有可能选择方案的数量为2^4=16
}

// 求解0/1背包问题的函数
void solve() {
        cout << "0/1背包求解方案" << endl; // 输出标题
        // 输出表头
        printf("%-10s%-20s%-10s%-10s%-10s\n", "序号", "选中物品", "总重量", "总价值", "能否装入");
        for (int i = 0; i < nsize; i++) { // 遍历所有可能的选择方案
                node1 temp; // 定义一个临时变量temp来存储当前选择方案
                temp.str.push_back('{'); // 添加左花括号
                temp.str.push_back(' ');
                for (int j = 0; j < n; j++) { // 遍历所有物品
                        if (i & (1 << j)) { // 检查当前选择方案是否选择了第j个物品
                                temp.str.push_back(j + '1'); // 如果选择了,则将物品编号添加到字符串中
                                temp.str.push_back(' ');
                                temp.weight += arr[j].weight; // 将物品的重量加到总重量中
                                temp.value += arr[j].value; // 将物品的价值加到总价值中
                        }
                }
                temp.str.push_back('}'); // 添加右花括号

                // 如果当前选择方案的总重量小于等于背包的最大承重且总价值大于当前最佳选择方案的总价值,则更新最佳选择方案
                if (temp.weight <= maxWeight && temp.value > ret.value) ret = temp;
                // 输出当前选择方案的序号、字符串表示、总重量、总价值和是否能装入背包
                printf("%-10lld%-20s%-10lld%-10lld%-10s\n", i + 1, temp.str.c_str(), temp.weight, temp.value, temp.weight <= maxWeight ? "能" : "否");
        }

        // 输出最佳选择方案的字符串表示、总重量和总价值
        printf("最佳方案为 选中物品:%s,总重量:%lld,总价值:%lld", ret.str.c_str(), ret.weight, ret.value);
}

// 主函数
signed main() {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 提高输入输出效率
        init(); // 初始化
        solve(); // 求解0/1背包问题
}

求解任务分配问题

有n(n≥1)个任务需要分配给n个人执行,每个任务只能分配给一个人,每个人只能执行一个任务。

第i个人执行第j个任务的成本是c[i][j](1≤i,j≤n)。求出总成本最小的分配方案

【问题求解】所谓一种分配方案就是由第i个人执行第j个任务,用(a1,a2,…,an)表示,即第1个人执行第a1个任务,第2个人执行第a2个任务,以此类推。全部的分配方案恰好是1~n的全排列。

这里采用穷举法求出所有的分配方案ps(全排列),再计算出每种方案的成本,比较求出最小成本的方案,即最优方案。以n=4,成本如下表所示为例讨论。

1.

排列问题,将4个任务进行全排列,列出所有的情况.

用内置函数next_premutation函数找到所有的全排序序列.

模板:

 
        vector<int> arr = { 1,2,3,4 };
        do {
                // 输出当前的排列
                for (int num : arr) {
                        cout << num << " ";
                }
                cout << endl;
        } while (next_permutation(arr.begin(), arr.end()));

2.

用内置函数next_premutation找到所有的全排序序列的前提是需要arr排序完毕.

 

//内置函数求全排序模板
#if 0

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
void init() {}
void solve() {}

signed main() {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        init();
        solve();


        vector<int> arr = { 1,2,3,4 };
        do {
                // 输出当前的排列
                for (int num : arr) {
                        cout << num << " ";
                }
                cout << endl;
        } while (next_permutation(arr.begin(), arr.end()));

}

#endif // 1

#if 1

#include<bits/stdc++.h> // 导入标准库头文件
using namespace std; // 使用标准命名空间
#define int long long // 将int类型定义为long long类型,便于处理大数
#define endl '\n' // 将endl定义为换行符

// 定义一个结构体node,用来存储一个分配方案及其总成本
struct node {
        vector<int>people = { 0,0,0,0 }; // 分配方案
        int total = 0; // 总成本
};

// 定义成本矩阵
vector<vector<int>> cost = {
        {9,2,7,8},
        {6,4,3,7},
        {5,8,1,8},
        {7,6,9,4}
};

// 定义一个包含任务序号的数组
vector<int>arr = { 1,2,3,4 };
// 定义一个变量ret,用来存储最优方案
node ret;

// 初始化函数
void init() {
        ret.total = INT_MAX; // 将最优方案的总成本初始化为最大值
}

// 求解任务分配问题的函数
void solve() {

        do {
                node temp; // 定义一个临时变量temp来存储当前分配方案
                for (int i = 0; i < arr.size(); i++) { // 遍历所有任务
                        temp.total += cost[i][arr[i] - 1]; // 累加当前分配方案的总成本
                }
                temp.people = arr; // 将当前分配方案赋值给temp的people字段
                if (ret.total > temp.total) ret = temp; // 如果当前分配方案的总成本小于最优方案的总成本,则更新最优方案

        } while (next_permutation(arr.begin(), arr.end())); // 生成下一个排列

        printf("最优方案:\n"); // 输出最优方案
        for (int i = 0; i < 4; i++) { // 遍历所有人
                printf("第%lld个人安排任务%lld\n", i + 1, ret.people[i]); // 输出每个人对应的任务
        }
        printf("总成本=%lld\n", ret.total); // 输出总成本
}

// 主函数
signed main() {
        ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 提高输入输出效率
        init(); // 初始化
        solve(); // 求解任务分配问题
}

#endif // 1

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

机器人支持回调接口配置(详细教程)

大家伙&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 一、前言 今天&#xff0c;给大家介绍一下&#xff0c;如何在机器人中配置回调地址和接口编写。很多时候我们可能有这样的场景&#xff0c;收到消息后&#xff0c;想自己处理一下消息的内…

用Python一键生成PNG图片的PowerPoint幻灯片

在当今的商业环境中,PowerPoint演示是展示和传递信息的常用方式。然而,手动将大量图像插入到幻灯片中往往是一项乏味且耗时的工作。但是,通过Python编程,我们可以轻松自动化这个过程,节省时间和精力。 C:\pythoncode\new\folderTOppt.py 在本文中,我将介绍如何使用Python、wx…

Rust开源Web框架Salvo源码编译

1.克隆源码: https://github.com/salvo-rs/salvo.git 2.进入salve目录并运行cargo build编译 编译成功 3.编译生成的库 4.安装salve-cli git clone --recursive https://github.com/salvo-rs/salvo-cli.git 编译salve-cli

人工智能万卡 GPU 集群的硬件和网络架构

万卡 GPU 集群互联:硬件配置和网络设计 一、背景 自从 OpenAI 推出 ChatGPT 以来,LLM 迅速成为焦点关注的对象,并取得快速发展。众多企业纷纷投入 LLM 预训练,希望跟上这一波浪潮。然而,要训练一个 100B 规模的 LLM,通常需要庞大的计算资源,例如拥有万卡 GPU 的集群。以…

Google Play 提示 “您的设备与此版本不兼容“ 解决方案

一、 问题概述Google Play提示“您的设备与此版本不兼容”&#xff0c;无法安装应用。 遇到问题的设备为Xiaomi Mi A3&#xff0c;查了下这台手机的基本信息&#xff0c;Android One系统&#xff0c;版本分为9.0、10.0、11.0。 二、 问题分析Google Play的过滤器 通常有以下5种…

【Nginx <末>】Nginx 基于 IP 地址的访问限制

目录 &#x1f44b;前言 &#x1f4eb;一、限制 IP 可以实现哪些功能 &#x1f440;二、 项目实现 2.1 访问控制实现 2.2 Nginx 配置中指定 IP 地址 &#x1f49e;️三、章末 &#x1f44b;前言 小伙伴们大家好&#xff0c;前面一段时间学习了 Nginx 的相关知识&#xff0c…

RT-DRET在实时目标检测上超越YOLO8

导读 目标检测作为计算机视觉的核心任务之一&#xff0c;其研究已经从基于CNN的架构发展到基于Transformer的架构&#xff0c;如DETR&#xff0c;后者通过简化流程实现端到端检测&#xff0c;消除了手工设计的组件。尽管如此&#xff0c;DETR的高计算成本限制了其在实时目标检测…

React useState基本类型变量的使用

在 React 中&#xff0c;useState 是一个 Hook&#xff0c;用于在函数组件中添加状态&#xff0c;它可以让函数组件拥有状态。基本使用方法如下&#xff1a; // App.jsx import React, { useState } from reactfunction App() {// 使用 useState 创建一个状态变量&#xff0c;初…

如何用Java实现SpringCloud Alibaba Sentinel的熔断功能?

在Java中使用Spring Cloud Alibaba Sentinel实现熔断功能的步骤如下&#xff1a; 添加依赖 在项目的pom.xml文件中添加Spring Cloud Alibaba Sentinel的依赖&#xff1a; <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud…

C语言——malloc和free用法和常见误区

最近写了个关于动态数组的代码&#xff0c;遇到了一个大坑&#xff0c;特此记录 先说结论&#xff1a; 1.利用malloc创建堆空间&#xff0c;大小最好设置大一点&#xff0c;不然后面存进去的值需要的空间过大会导致各种的堆、指针问题 2.只能使用realloc对已经创建的空间进行修…

没有电商经验的人去操作抖音小店,难度大不大?好操作吗?

大家好&#xff0c;我是电商小V 很多新手小伙伴想去操作抖音小店项目&#xff0c;咨询的最多的问题就是我没有电商运营的经验可以去操作吗&#xff1f; 当然是可以操作的&#xff0c;抖音小店项目对于新手来说是一个非常友好的项目&#xff0c;很多小伙伴都是感觉没有电商经验去…

C++——list的实现以及源码

前言&#xff1a; 最近学习了clist的实现&#xff0c;这让我对迭代器的理解又上升了一个新的高度&#xff0c;注意&#xff1a;代码里的list是放在一个叫zgw的命名空间里边&#xff0c;但是在实现list的代码中没有加namespace&#xff0c;这里给个注意&#xff0c;以后复习时能…

整理了10个靠谱且热门的赚钱软件,适合普通人长期做的赚钱副业

作为一名普通的上班族&#xff0c;我们每天都在辛勤工作&#xff0c;但工资的增长速度却如同蜗牛般缓慢。不过&#xff0c;别担心&#xff0c;信息时代总是带给我们无尽的惊喜&#xff01;今天&#xff0c;我将为大家推荐一些赚钱的宝藏软件&#xff0c;让你在闲暇之余轻松实现…

五分钟搭建一个Suno AI音乐站点

五分钟搭建一个Suno AI音乐站点 在这个数字化时代&#xff0c;人工智能技术正以惊人的速度改变着我们的生活方式和创造方式。音乐作为一种最直接、最感性的艺术形式&#xff0c;自然也成为了人工智能技术的应用场景之一。今天&#xff0c;我们将以Vue和Node.js为基础&#xff…

三十六计的笔记

系列文章目录 三十六计的笔记 文章目录 系列文章目录1、瞒天过海2、围魏救赵3、借刀杀人4、以逸待劳5、趁火打劫6、声东击西7、无中生有8、暗渡陈仓9、隔岸观火10、笑里藏刀11、李代桃僵12、顺手牵羊13、打草惊蛇14、借尸还魂15、调虎离山16、欲擒故纵17、抛砖引玉18、擒贼擒王…

牛客NC302 环形数组的连续子数组最大和【中等 动态规划 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/e9f3282363844355aa51497c5410beee 思路 动态规划 两种情况&#xff08;首位相连的&#xff09;和首位不相连的 首尾相连的可以算最小的连续子数组得出&#xff0c;sum-就是。Java代码 import java.util.*;pub…

第20届文博会:“特别呈现”—周瑛瑾雷米·艾融双个展,著名美术评论家,批评家彭德教授对周瑛瑾作品进行评论

周瑛瑾不是学院派艺术家&#xff0c;但在彩墨画领域的天赋超出中国八大美院的同类型画家。相比具有批判意识的当代艺术&#xff0c;他的彩墨艺术如同我们这个苦难世界的创可贴和安慰剂。当我面对他的彩墨画&#xff0c;首先是惊艳&#xff0c;随之想到屈原的离骚&#xff0c;还…

slint esp32 tokio

源码&#xff1a;https://github.com/xiaguangbo/slint_esp32_tokio cpu 是 esp32c2&#xff0c;屏幕是 ili9341&#xff0c;触摸是 xpt2046&#xff0c;使用 spi 半双工 不使用DMA&#xff08;esp-rs还没支持&#xff09;&#xff0c;SPI 40M&#xff0c;240*320全屏刷新为1.5…

Windows、Linux下,基于QT的打包方法

整理这篇文档的意义在于&#xff1a;自己走了很多弯路&#xff0c;淋过雨所以想为别人撑伞&#xff0c;也方便回顾&#xff0c;仅供参考 ps: 第一次做Windows下打包&#xff0c;用了2小时&#xff0c;第二次20秒第一次做Linux(ubuntu)下打包&#xff0c;用了8小时&#xff0c;…

Linux 内核

查看内核的发行版 $ uname -r 5.4.0-150-genericcd /lib/modules/5.4.0-150-generic, 内核源码所在的位置&#xff1a;/usr/src 这里的内核源码路径&#xff08;–kernel-source-path&#xff09;即为&#xff1a; cd /usr/src/linux-headers-5.4.0-150-generic/ 临时生效: …