【算法作业】均分卡牌,购买股票

问题描述

  1. John 有两个孩子,在 John病逝后,留下了一组价值不一定相同的魔卡, 现在要求你设计一种策略,帮John的经管人将John的这些遗产分给他的两个孩子,使得他们获得的遗产差异最小(每张魔卡不能分拆)。

  2. 假设已知某股票连续若干天的股价,并且如何时候你手上只能由一支股票,即如果你要买入就得先将手上股票卖出,设计一个算法来计算你所能获取的最大利润。你最多可以完成 k笔交易。也就是说,你最多可以买k 次,卖 k 次。

    输入:k = 2, prices = [3,2,7,5,1,4]
    输出:87-2  +  4-1
    

解题思路

T1

这是一个贪心算法问题还是一个动规问题呢?

在思考这道题的时候,我犯了过于经验主义的错误。因为和之前遇见的题目有过类似的,觉得是贪心,所以没有多去求证,就框框把代码写完了,其实贪心并不能得到全局最优解(😁十分感谢看到我博客的同班同学的提醒)

贪心的思路是:

  1. 将所有的魔卡按照价值从大到小排序。
  2. 从价值最高的魔卡开始,依次分配给两个孩子中当前遗产较少的那个孩子。
  3. 重复步骤2直到所有的魔卡都被分配完毕。

这样是有问题的,直接举反例,当 N = 2 时 cards = [5, 3, 2, 2, 2, 2] 贪心求解ans = 2。然而正确的最优解应该为0,两个孩子分别[5, 3]和[2, 2, 2, 2]

因此,正确解法为动态规划

动态规划的思路是:

  1. 求取所有卡牌价值之和sum
  2. 然后转换成01背包问题,商品的价值和重量都等于卡牌的价值,背包的上限m = sum/2,尽可能的往这个背包里装商品使其价值最大,即最靠近sum/2。求得此时的最大价值dp[n][sum/2]ans
  3. 最后此问题的解为sum - 2*ans

T2

那么这道题到底是贪心还是动规呢?

我们知道动规有一道经典例题,就是非升子序列,不觉得这题有几分相似,都是必须从前往后求最优。其实要证明贪心算法不行只要举个反例就行了。

于是就根据经验按照动规的思路来思考。考虑使用二维数组dp[i][j],代表当前状态的最大利润,i代表当前是第i次买卖,j代表当前是第j天。

对于每个状态都有买和不买。为什么是买和不买呢,不是还有卖吗?其实是赚钱和不赚钱这两种选择,赚钱是卖与买之间的差值。所以这道题比一般的动态规划要更复杂些。

对于每一次买卖,必须有买才有卖,先用maxDiff包括因为买股票亏的钱,一开始由于没有股票,就等于-prices[1]。这个亏的钱也完全不是负数亏的钱,还要包括之前(上一次买卖)因为赚钱累计的成本,这个maxDiff就是代表本次买卖状态下的累计成本(比较难理解)。所以 m a x D i f f = m a x ( m a x D i f f , d p [ i − 1 ] [ j ] − p r i c e s [ j ] ) maxDiff = max(maxDiff, dp[i-1][j] - prices[j]) maxDiff=max(maxDiff,dp[i1][j]prices[j])

对于每一天,都有去赚钱和不赚钱。不赚钱利润等于昨天的利润,去赚钱的利润等于累计成本maxDiff加上prices[j],因此 d p [ i ] [ j ] = m a x ( d p [ i ] [ j − 1 ] , p r i c e s [ j ] + m a x D i f f ) dp[i][j] = max(dp[i][j-1], prices[j] + maxDiff) dp[i][j]=max(dp[i][j1],prices[j]+maxDiff)

在样例下,dp运算结果如下所示。

prices327514
dp[1][j]005555
dp[2][j]005558

这个dp[k][n]就是answer。

完整代码

T1

#include <bits/stdc++.h>
using namespace std;int main() {// 输入魔卡数量int n;cout << "请输入魔卡数量:";cin >> n;// 输入每张魔卡的价值int cards[101],sum=0;cout << "请输入每张魔卡的价值:" << endl;for (int i = 1; i <= n; ++i) {cin >> cards[i];sum += cards[i];}//    int middle; 
//    if(sum % 2 ==0)
//    	middle = sum/2;
//    else 
//    	middle = sum/2 + 1;
//    cout<<"middle = "<<middle<<endl;int dp[101][1001];memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++)for(int j=cards[i];j<=sum/2;j++)if(cards[i] <= j)// 如果装的下 dp[i][j] = max(dp[i-1][j],dp[i-1][j-cards[i]] + cards[i]);else dp[i][j] = dp[i-1][j];int ans = dp[n][sum/2];cout<<ans<<endl;for(int i=1;i<=n;i++){for(int j=1;j<=sum/2;j++)cout<<dp[i][j]<<" ";cout<<endl;}cout<<"ans = "<<sum-2*ans;return 0;
}/* sample input
8 
2 5 6 7 1 7 4 36
5 3 2 2 2 2 
*/

输出结果

请输入魔卡数量:8
请输入每张魔卡的价值:
2 5 6 7 1 7 4 3
17
0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
0 0 0 0 5 5 7 7 7 7 7 7 7 7 7 7 7
0 0 0 0 0 6 7 7 7 7 11 11 13 13 13 13 13
0 0 0 0 0 0 7 7 7 7 11 11 13 14 14 14 14
1 1 1 1 1 1 7 8 8 8 11 12 13 14 15 15 15
0 0 0 0 0 0 7 8 8 8 11 12 13 14 15 15 15
0 0 0 4 4 4 7 8 8 8 11 12 13 14 15 16 17
0 0 3 4 4 4 7 8 8 10 11 12 13 14 15 16 17
ans = 1
请输入每张魔卡的价值:
5 3 2 2 2 2
8
0 0 0 0 5 5 5 5
0 0 3 3 5 5 5 8
0 2 3 3 5 5 7 8
0 2 3 4 5 5 7 8
0 2 3 4 5 6 7 8
0 2 3 4 5 6 7 8
ans = 0

T2

#include<bits/stdc++.h>
using namespace std;
int main(){int n,k,prices[100],dp[101][101]; // 动态规划数组大小修改为dp[101][101]cin>>n>>k;memset(dp,0,sizeof(dp));memset(prices,0,sizeof(prices));for(int i=1;i<=n;i++)cin>>prices[i];for(int i=1;i<=k;i++){int maxDiff = -prices[1]; // 数组prices的下标从1开始for(int j=1;j<=n;j++){ dp[i][j] = max(dp[i][j-1],prices[j] + maxDiff);maxDiff = max(maxDiff, dp[i-1][j] - prices[j]);}}cout<<dp[k][n]<<endl;// 打印dp数组cout<<"|dp|";for(int i=1;i<=n;i++)cout<<i<<"|";cout<<endl;cout<<"|";for(int i=1;i<=n+1;i++)cout<<"-|";cout<<endl;for(int i=1;i<=k;i++){cout<<"|"<<i<<"|";for(int j=1;j<=n;j++)cout<<dp[i][j]<<"|";cout<<"\n";}return 0;
}/* simple input
6 2
3 2 7 5 1 4
*/

输出结果

6 2
3 2 7 5 1 4
8
|dp|1|2|3|4|5|6|
|-|-|-|-|-|-|-|
|1|0|0|5|5|5|5|
|2|0|0|5|5|5|8|

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搜索引擎的设计与实现(三)

目录 5 系统详细实现 5.1实现环境配置 5.2功能实现 5.2.1 建立索引 5.2.2 文件搜索实现 5.2.3 数据库的连接配置 5.2.4 数据库搜索实现 5.2.5 后台数据编辑实现 前面内容请移步 搜索引擎的设计与实现&#xff08;二&#xff09; 免费源代码&毕业设计论文 搜索…

git-删除workspace.xml的跟踪

问题描述 .gitignore 文件内容如下&#xff1a; .pyc *.pyc user_files/ .vscode/ __pycache__//.idea/misc.xml /.idea/modules.xml /.idea/inspectionProfiles/profiles_settings.xml /.idea/inspectionProfiles/Project_Default.xml /.idea/batrp_webbackend-server-dev.i…

NARUTO 复现记录

1 环境配置 下载项目&#xff0c;一定要 git 下载全项目&#xff0c;下载完后要检查third_parities 里面的coslam和neural_slam_eval 文件全不全。 git clone --recursive https://github.com/oppo-us-research/NARUTO.git 环境配置 注意 bash scripts/installation/conda…

番外篇 | 利用PyQt5+YOLOv5来搭建目标检测系统(附可视化界面+功能介绍+源代码)

前言:Hello大家好,我是小哥谈。PyQt5是一个Python绑定的Qt库,是用于创建图形用户界面(GUI)和其他应用程序组件的工具包。PyQt5提供了许多GUI元素,如按钮、文本框、标签等,也提供了许多Qt的功能,如网络、数据库、XML等。通过PyQt5可以在Python中使用Qt的丰富功能和强大的工…

克服亏损的负面影响 学学现货白银止损的方法

一个多月以前&#xff0c;现货黄金的上涨还十分强劲&#xff0c;一度还逼近历史的高位30大关。但是我们看近半个月以来&#xff0c;现货白银价格出现了调整。很多在高位买入的投资者都承受了较大的亏损&#xff0c;这时候就凸显出了现货白银止损的作用。如果投资者能够通过近期…

Git 基础使用(2) 分支管理

文章目录 分支概念分支使用查看分支分支创建分支切换分支合并合并冲突分支删除 分支管理快进模式分支策略内容保存错误处理 分支概念 &#xff08;1&#xff09;分支概念 Git分支是指在版本控制系统Git中&#xff0c;用来表示项目的不同工作流程或开发路径的一个重要概念。通过…

【cmake】Windows 环境下编译第三方依赖源码(以编译Xerces库为例)

第三方依赖源码的编译分为两种&#xff0c;一种是使用 Configure 脚本编译&#xff0c;另一种是使用 CMakeLists.txt 编译。Xerces 3.2.3 的编译方式是 CMakeLists.txt 脚本编译。 必要软件&#xff1a; CMake &#xff08;CMake | Download&#xff09;Visual Studio 2019&a…

前端AJAX讲解

目录 1.AJAX是什么&#xff1f; 2.异步交互和同步交互 3.AJAX常见应用情景和优缺点 4.AJAX的优缺点 5.AJAX发送异步请求&#xff08;四步操作&#xff09; 6.经典案例 1.AJAX是什么&#xff1f; AJAX即“Asynchronous JavaScript and XML”&#xff08;异步的JavaScript与…

指针基础实践

文章目录 1.声明指针2.初始化指针3.指针地址和大小&#xff0c;值4.指针解引用,修改值5.指针指向堆内存&#xff0c;修改值6.申请堆内存并释放7.数组释放8.指针运算9.指针递增10.指针递减11.指针常量12.常量指针13.常量指针指向常量 1.声明指针 2.初始化指针 3.指针地址和大小…

【数据结构】二叉树(Binary Tree)

文章目录 一、树的概念及结构二、二叉树的概念及结构1.二叉树的概念2.特殊的二叉树3.二叉树的性质 三、二叉树的存储顺序存储链式存储 四、二叉树的实现1.创建二叉树2.二叉树的遍历前序遍历中序遍历后序遍历层序遍历根据遍历顺序创建二叉树 3.二叉树的基本操作1.总结点个数2.二…

ctfshow之_萌新web9至web10

一、访问在线靶场ctfshow 1、web9 如下图所示&#xff0c;进入_萌新赛的web9问题&#xff0c;题目提醒flag在config.php中&#xff1a; 如上图所示&#xff0c;可以get传参&#xff0c;且传入的参数需要正则匹配system、exec、highlight&#xff0c;且不区分大小写&#xff0…

C++设计模式|创建型 5.原型模式

1.什么是原型模式&#xff1f; 原型模式⼀种创建型设计模式&#xff0c;该模式的核⼼思想是基于现有的对象创建新的对象&#xff0c;⽽不是从头开始创建。 在原型模式中&#xff0c;通常有⼀个原型对象&#xff0c;它被⽤作创建新对象的模板。新对象通过复制原型对象的属性和状…

Mac IDEA 自动补全mybatis sql语句

导航 Mac IDEA 自动补全mybatis sql语句一、点击IDEA 右侧Database选项二、选择添加对应数据库三、输入数据库信息和方案四、输入数据库信息和方案五、成功 Mac IDEA 自动补全mybatis sql语句 背景&#xff1a; 想在Mapper中&#xff0c;能够实现自动检索数据库表和对应的字段…

QT日志类SimpleQtLogger的简单记录

在现代软件开发中&#xff0c;日志记录是必不可少的部分。它不仅帮助开发者在调试和维护软件时了解程序的运行状态&#xff0c;还能提供关键的错误信息。对于使用Qt框架开发应用程序的开发者来说&#xff0c;选择一个合适的日志库至关重要。本文将详细介绍Qt日志库SimpleQtLogg…

web前端之sass中的颜色函数、active按钮激活、hover鼠标悬浮、disabled禁用、scss循环、css

MENU 效果图htmlsassscss编译后的css页面css 效果图 注意查看蓝色按钮。 html <div class"box"><button class"btn type_1">按钮</button><button class"btn type_2">按钮</button><button class"btn ty…

一文读懂通用漏洞评分系统CVSS4.0:顺带理清CVE、CWE及其与CVSS之间的关系

事件响应和安全团队论坛 (FIRST&#xff0c;Forum of Incident Response and Security Teams) 于 2023 年 11 月 1 日正式推出第四版通用漏洞评分系统 (CVSS 4.0&#xff0c;Common Vulnerability Scoring System version 4.0)。CVSS 4.0 是评估计算机系统安全漏洞严重性的行业…

C++ 多态性

一 多态性的分类 编译时的多态 函数重载 运算符重载 运行时的多态 虚函数 1 运算符重载的引入 使用C编写程序时&#xff0c;我们不仅要使用基本数据类型&#xff0c;还要设计新的数据类型-------类类型。 一般情况下&#xff0c;基本数据类型的运算都是运算符来表达&#x…

【C++】详解C++的模板

目录 概念 ​编辑 语法 函数模板 类模板 非类型模板参数 模板的特化 函数模板特化 类模板特化 全特化 偏特化 分离编译 概念 模板是C中非常厉害的设计&#xff0c;模板把通用的逻辑剥离出来&#xff0c;让不同的数据类型可以复用同一种模板的逻辑&#xff0c;甚至可以…

Flutter 中的 DataTable 小部件:全面指南

Flutter 中的 DataTable 小部件&#xff1a;全面指南 在Flutter的Material组件库中&#xff0c;DataTable是一个用于展示数据的表格组件&#xff0c;它允许开发者以一种结构化和可滚动的方式展示数据集。DataTable非常适合展示详细信息&#xff0c;如表格数据、统计数据或配置…

PHP黑魔法之md5绕过

php本身是一种弱语言,这个特性决定了它的两个特点: 输入的参数都是当作字符串处理变量类型不需要声明,大部分时候都是通过函数进行类型转化php中的判断有两种: 松散比较:只需要值相同即可,类型不必相同,不通类型比较会先转化为同类型,比如全数字字符串和数字比较,会比…