用“双优先队列”方法解决双/多指标的规划问题

PS:本文要解决的问题不算难度很大的问题,但“双优先队列”的方法是以前没有见过的,昨天睡觉突然想到的,以时间Ο(logn),空间O(n)的较好代价解决一类问题,记录一下

问题抽象:

算法的设计中常会出现这种需求,一个对象有多种比较策略,而不同的比较往往会产生矛盾,目的是在一项指标的约束下实现另一指标的最优化。

描述的云里雾里,其实例子比较好理解,比方说,KFC的外卖小哥们每人有一个电驴子,不同的剩余电量不同,远距离的单需要电多的车子去送,而派出小哥剩的电越多,成本就越高(这个好像没道理。。先设想这个情景吧)。那么对于一批订单,怎么决定派出的外卖小哥能让成本最优呢?

分析问题:

看起来可以用贪心的思想解决。车子有两个指标:电量和成本,问题的难点在于,这二者往往是冲突的,不论从哪出发进行贪心都很难证明最优。合理的贪心策略描述为:对于订单距离需求大向小排序,总在剩余的满足当前最大需求(电量大于等于距离)的小哥中派出成本最低的。

解决方案:

采用两个优先队列,对外卖小哥定制两种类的表达:ElecFirstBro和CostFirstBro,CostFirstBro支持参数为const ElecFirstBro &的构造,重载比较符,使两个队列中分别以电量剩余优先成本小优先保存数据。

先将小哥全存入ElecFirstBro的队列中。

对订单反向排序,从大到小迭代(因为在远距离中没有采用的小哥也许在近距离的比较中反而可以采用,所以应当由大到小比较,保留每个没采用的Bro)。每次迭代中,用循环将所有适用当前距离需求的全出队,同时加入CostFirstBro队列。调整完毕后,从CostFirstBro弹出队首(显然是成本最小的)。

 1 struct ElecFirstBro
 2 {
 3     int elec;
 4     int cost;
 5 };
 6 bool operator< (const ElecFirstBro &_B1, const ElecFirstBro &_B2) { return _B1.elec < _B2.elec; }
 7
 8 struct CostFirstBro
 9 {
10     int elec;
11     int cost;
12     CostFirstBro(const ElecFirstBro &_B) :elec{ _B.elec }, cost{ _B.cost } {}
13 };
14 bool operator< (const CostFirstBro &_B1, const CostFirstBro &_B2) { return _B1.cost > _B2.cost; }
15
16 class Solution
17 {
18     int minimum_cost(const vector<int> &_Require, const vector<ElecFirstBro> &_Bros)
19     {
20         priority_queue<ElecFirstBro> epq;
21         for (const auto &bro : _Bros)
22         {
23             epq.push(bro);
24         }
25         priority_queue<CostFirstBro> cpq;
26         int sum = 0;
27         for (const auto req : _Require)
28         {
29             while (!epq.empty() && epq.top().elec >= req)
30             {
31                 cpq.push(CostFirstBro(epq.top()));
32             }
33             if (cpq.empty())
34             {
35                 return -1;
36             }
37             else
38             {
39                 sum += cpq.top().cost;
40                 cpq.pop();
41             }
42         }
43         return sum;
44     }
45 };
时间: 2024-10-24 16:04:20

用“双优先队列”方法解决双/多指标的规划问题的相关文章

3个方法解决百度网盘限速 (2018-07-20)

360网盘关闭后,百度似乎要成为国内网盘的唯一选择,然而百度云下载速度太慢,显然是被限速了,吃相难看.下面有3个方法解决百度网盘限速的问题,演示的下载文件是大于1G的一个 War3.zip 单文件(用拖拽的方法打开,否则显示页面不存在),使用的宽带是电信20M,百度限速后的下载速度只有256KB/s,而理论上的下载速度是可以达到2M/s的.奶酪也将持续关注百度网盘限速的问题. 1. 百度网盘下载助手脚本 - 2018-04-15更新[最长久] 最早是网友"有一份田"制作的脚本百度下载助

使用堆和队列数据结构解决迷宫问题

python实现迷宫问题的栈和队列的解决方法: #迷宫问题#表示迷宫的颜色,0表示路通,1表示围墙maze=[ [1,1,1,1,1,1,1,1,1,1], [1,0,0,1,0,0,0,1,0,1], [1,0,0,1,0,0,0,1,0,1], [1,0,0,0,0,1,1,0,0,1], [1,0,1,1,1,0,0,0,0,1], [1,0,0,0,1,0,0,0,0,1], [1,0,1,0,0,0,1,0,0,1], [1,0,1,1,1,0,1,1,0,1], [1,1,0,0,0

Laravel4快速安装方法,解决Laravel4安装速度慢

Laravel4原始安装方法 Laravel4 是构建在 Composer 之上的, 之前的安装方法是如下: composer create-project laravel/laravel your-project-name --prefer-dist 1 composer create-project laravel/laravel your-project-name --prefer-dist 然后再 composer install 1 composer install 十分钟过去了 ….

JavaScript高级程序设计--对象,数组(栈方法,队列方法,重排序方法,迭代方法)

1.使用对象字面量定义对象 var person={}; 使用这种方式创建对象时,实际上不会调用Object构造函数. 开发人员更喜欢对象字面量的语法. 2.有时候需要传递大量可选参数的情形时,一般来讲使用对象字面量来封装多个可选参数. 3.对象属性的点表示法与方括号表示法的区别 (1)功能上:两者没区别 (2)但是方括号的有点是可以通过变量来访问属性 例如: var person={ name:"Nic" } 点表示法:person.name 方括号表示法:var prop=“nam

Maven构造版本号的方法解决浏览器缓存问题

需要解决的问题 在做WEB系统开发时,为了提高性能会利用浏览器的缓存功能,其实即使不显式的申明缓存,现代的浏览器都会对静态文件(js.css.图片之类)缓存.但也正因为这个问题导致一个问题,就是资源的缓存逻辑有时出现问题后服务器的最新版本文件无法更新客户端的缓存. 这个问题会给用户产生许多的困扰,当然首先是测试人员会很头痛,一些看起来没有修复的bug为什么开发要说做好了?这种时候我会无奈的说:ctrl+f5刷新一下.但这毕竟不是解决问题的方法. 思路与方法考虑 思路 之前没有着手处理过这样的问题

Array的队列方法&amp;重排序方法—— JS学习笔记2015-6-27(第68天)

队列方法 相对于栈数据结构的后进先出[LIFO]访问规则,队列数据结构的访问规则是先进先出[FIFO] 这里提到一个方法  shift(); 它能够移除数组中的第一个项,并返回该项,同时将数组长度减1:// 有点像pop() 实例: var colors = ['red','green']; var item = colors.shift(); alert(colors);  // green alert(item);  // red alert(colors.length)  // 1; 同时

VS2013+openCV3.0无脑配置方法+解决警告问题【windows平台】

VS2013+openCV3.0无脑配置方法+解决警告问题[windows平台] 本文介绍如何配置VS+openCV环境,并解决“opencv 3.0 warning C4819: 该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 Unicode 格式以防止数据丢失的”警告 参考博客: http://my.phirobot.com/blog/2014-02-opencv_configuration_in_vs.html 下载 openCV 下载 Opencv for Windo

今天和组内一起写代码时碰到了一个关于命名冲突的问题,最后用js命名空间的方法解决的。

//第一步,首先创建一个全局变量,可以放在自己的js方法库中方便以后用,这个就是用来注册命名空间的方法. ns = function(namespace){ var arr = namespace.split('.');  //将传入的字符串如"com.test.lzn"以'.'隔开做成一个数组 var strNamespace = ""; //这个是为了保存每一步循环进去的包名 for(var i=0;i<arr.length;i++) { if(i!=0)

7种方法解决移动端Retina屏幕1px边框问题

在Reina(视网膜)屏幕的手机上,使用CSS设置的1px的边框实际会比视觉稿粗很多.在之前的项目中,UI告诉我说我们移动项目中的边框全部都变粗了,UI把他的设计稿跟我的屏幕截图跟我看,居然真的不一样.没有办法,只有在后面的版本中去修改了,但是要改的话,需要知道是为什么.所以查了很多资料,终于搞懂了这个问题,并且总结了几种方法. 造成边框变粗的原因 其实这个原因很简单,因为css中的1px并不等于移动设备的1px,这些由于不同的手机有不同的像素密度.在window对象中有一个devicePixe