(C/C++)区间调度问题的解决及输出:动态规划、贪心算法(递归、递推)

2023-05-16

给定n个活动,其中的每个活动ai包含一个起始时间si与结束时间fi。设计与实现算法从n个活动中找出一个最大的相互兼容的活动子集S。
要求:分别设计动态规划与贪心算法求解该问题。其中,对贪心算法分别给出递归与迭代两个版本的实现。

思路

动态规划

动态规划的思路则对此问题来说较为复杂,定义Sij为在i任务结束之后,j任务开始之间所包含的任务的子集。定义两个虚拟任务ai、an+1,则问题对应了S0,n+1的解。Sij的元素数量则对应了任务的数量。通过递归方程可知复杂度为O(n3),可通过设定另一个二维数组以输出元素。
递归方程

贪心算法

贪心算法的思路很简单,非空子集Sij,若am结束的时间最早,则有:
贪心准则:am一定属于Sij的某个最优解且Sim为空。
贪心准则的证明:
Aijj为Sij最优解,另其中的任务按照结束时间递增排序,令ak是Aij的第一个结束的任务,如果ak=am,则证明成立。否则我们将ak用am替换,则它成为了另一个解A’ij,同样是最优解。
所以即将任务以结束时间递增排序,第一个结束的任务一定在最优解中,依次找出子问题中最先结束,且开始时间在前一个解最后一个任务结束之间之后。复杂度为O(n)。同时很容易得出有递归和递推两种形式,一般采用递推。
贪心算法
递归
递推

#include <iostream>
#include <vector>
#define TASK_COUNT 8
using namespace std;
int finish[TASK_COUNT + 2] = { -1,2,4,6,7,8,9,12,15,255};
int start[TASK_COUNT + 2] = { -1,1,2,3,3,1,7,10,13,255};
int _count[TASK_COUNT + 2][TASK_COUNT + 2];
int p[TASK_COUNT + 2][TASK_COUNT + 2];
void recursive(int* start,int* finish,int begin,int end) {
	int m = begin + 1;
	while (m <= end) {
		if (start[m] >= finish[begin]) {
			break;
		}
		m++;
	}
	if (m <= end) {
		cout << m << " ";
		recursive(start, finish, m, end);
	}
}

void iterative(int* start, int* finish) {
	int len = TASK_COUNT;
	int pre = 0;
	for (int i = 1; i <= len; i++) {
		if (start[i] >= finish[pre]) {
			cout << i << " ";
			pre = i;
		}
	}
}


void dp(int* start, int* finish) {
	for (int len = 2; len <= TASK_COUNT + 2; len++) {
		for (int begin = 0; begin <= TASK_COUNT + 1; begin++) {
			int end = begin + len - 1;
			int max = 0;
			int slice = 0;
			for (int k = begin + 1; k <= end - 1; k++) {
				if (start[k] >= finish[begin]&&finish[k]<=start[end]) {
					int temp = _count[begin][k] + _count[k][end] + 1;
					if (temp > max) {
						max = temp;
						slice = k;
					}
				}
			}
			p[begin][end] = slice;
			_count[begin][end] = max;
		}
	}
}

void printDp( int begin, int end) {
	int pos = p[begin][end];
	if (pos == 0)
		return;
	cout << pos << " ";
	printDp(begin, pos);
	printDp(pos, end);
	
}

int main(void) {
	for (int i = 0; i <= TASK_COUNT; i++) {
		cout << i << ":";
		for (int j = 0; j < start[i]; j++) {
			cout << "  ";
		}
		for (int j = start[i]; j < finish[i]; j++) {
			cout << "■";
		}
		cout << endl;
	}
	recursive(start, finish, 0, TASK_COUNT);
	cout << endl;
	iterative(start, finish);
	cout << endl;
	for (int i = 0; i <= TASK_COUNT + 2; i++) {
		for (int j = 0; j <= TASK_COUNT + 2; j++) {
			_count[i][j] = 0;
			p[i][j] = 0;
		}
	}
	dp(start, finish);
	cout << _count[0][TASK_COUNT + 1] << endl;
	printDp(0, TASK_COUNT + 1);
	system("pause");
	return 0;
}

运行结果

运行结果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(C/C++)区间调度问题的解决及输出:动态规划、贪心算法(递归、递推) 的相关文章

随机推荐

  • 基金理财语录

    1 xff1a 理财不是发财 2 xff1a 市场的走势和我们的意愿无关 3 xff1a 不当抱死一只基金 一支基金长期业绩不行就是不行 4 xff1a 最好是用红利再投资 5 xff1a 不是市场有了巨变 xff0c 而是人心发生了转变
  • 《时间管理机》笔记

    1 xff1a 实践是检验真理的一切标准 2 xff1a 时间管理是一种生活方式 xff0c 是一种习惯 3 xff1a 或许你对写报告时候聊3分钟QQ或者微信或者刷微博不以为然 xff0c 但是我要告诉你 xff0c 曾经有人做过这样的实
  • Unix Shell中单引号、双引号字符、反斜杠、反引号的使用

    在执行shell脚本的时候 xff0c shell将会对脚本中的行进行解释 xff0c 然后执行 xff1b 对于一些特殊处理的句子 xff0c 我们可以使用引号或者反斜线来避免shell解释执行之 如下 xff0c 当在命令行中输入 xf
  • 我的基金组合和选择标准

    基金组合 xff1a 注意 xff1a 自己的基金投资组合每半年和一年做一次审查 xff0c 定投基金就要有长期投资的准备 xff0c 要有长期标的 xff0c 如果基金业绩不好很长时间就要放弃 xff0c 赚钱才是第一 xff0c 选择中
  • 股票

    选股 xff1a 一般大牛股都要早于大盘开始拉升 市盈率要低于20算低估 最好是低于10 要找次新股 xff0c 最好不要分红除权过后的股票 有行情的时候 xff0c 可以选择宽基指数基金 xff0c 快进快出 如沪深300 牛市使劲买 x
  • 《亲密关系》读书笔记

    1 xff1a 对家庭死忠 xff1a 对家庭成员的模仿塑造了自我 xff0c 而丢失了自我 xff0c 在面对亲密关系的时候 xff0c 我们需要找到自己灵魂内心最真实的感受 xff0c 而不是固守成规 xff0c 模仿家中 xff0c
  • 价差交易

    1 xff1a 尽量瞄准价差变化大得时候开仓 2 xff1a 在升水价差时期 xff0c 价差在扩大之后 xff0c 常常会收敛回到前面得波谷得地方 3 xff1a 价差有风险 xff0c 学会资金管理 xff0c 要学会止损 4 xff1
  • 天勤开发介绍

    5 回测暂不支持 获取多合约K线 若在回测时获取多合约K线 xff0c 程序会报出获取数据超时异常
  • linux下C++如何连接mysql数据库

    在Linux下 xff0c 我们可以通过MySQL提供的C API连接数据库 使用C API连接mysql数据库除了要安装mysql client和mysql server xff0c 还需要安装mysql的开发包mysql devel 我
  • Qt5安装mysql驱动

    转载 xff1a https blog csdn net D759378563 article details 77720830 utm medium 61 distribute pc relevant none task blog Blo
  • Qt Creator报错无法引用某个库函数的问题

    target link libraries detector nvinfer nvinfer plugin nvparsers OpenCV LIBS 34 stdc 43 43 fs 34 今天编译一个开源库 xff0c 用cmake构建
  • Qt在使用QMap时候出现mumap_chunk():invalid pointer问题

    之前用Qt开发了一个上位机软件 xff0c 在移植到树莓派4的时候出现了问题 xff0c 软件运行报错 xff1a mumao chunk invalid pointer 在调试发现是在使用QMap的T amp const key 时候 问
  • ubuntu下 QT 连接sqlite数据库报错问题一招解决(QSqlDatabase: * driver not loaded )

    sudo apt get install libqt5 把所有的qt5库都装上 xff0c 就是干 xff01 参考博客 xff1a ubuntu下 QT 连接各种数据库报错解决 xff08 QSqlDatabase driver not
  • 零基础入门无人机--无人机姿态--2

    四旋翼在其四个轴臂上四个桨的高速转动作用下 xff0c 会受到四个桨的拉力 xff0c 拉力方向与机身垂直 xff0c 当四个桨产生的拉力总和大于机身重力时 xff0c 飞机处于上升状态 xff1b 当总拉力小于机身重力时 xff0c 飞机
  • VAssist安装的时候破解版一样要输入注册码的时候

    下载了破解版的vassist助手点击了安装之后 xff0c 需要将VA X dll文件放在对应vs版本文件下的路径内替换原有的动态库 详细请看转载 xff1a https blog csdn net superdu1 article det
  • VS+Qt 运行时候qDebug没有黑窗口弹出并且不打印信息的问题

    点击运行项目的工程 属性 连接器 如上图所示
  • Qt连接MySQL数据库出现错误信息:Driver not loaded

    首先请参考这篇博文 xff1a https blog csdn net silence lu article details 81702580 按照这篇博文设置完之后 xff0c 如果还不能连接上 xff0c 那么请将mysql服务器重启
  • 如何获取mysql数据库中的表的列名

    SELECT COLUMN NAME FROM information schema COLUMNS WHERE table name 61 39 需要的标名 39
  • 二叉树高度的三种计算方法

    计算二叉树的高度可以采用几种不同的算法 算法一 xff1a 采用后序遍历二叉树 xff0c 结点最大栈长即为二叉树的高度 xff1b 算法二 xff1a 层次遍历二叉树 xff0c 最大层次即为二叉树的高度 xff1b 算法三 xff1a
  • (C/C++)区间调度问题的解决及输出:动态规划、贪心算法(递归、递推)

    给定n个活动 xff0c 其中的每个活动ai包含一个起始时间si与结束时间fi 设计与实现算法从n个活动中找出一个最大的相互兼容的活动子集S 要求 xff1a 分别设计动态规划与贪心算法求解该问题 其中 xff0c 对贪心算法分别给出递归与