ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2.1 动态规划

2022-01-27 15:59:31  阅读:201  来源: 互联网

标签:状态 决策 问题 vector 阶段 2.1 动态 规划 最优


1. 定义

动态规划法:把多阶段过程转化为一系列单阶段问题,利用个各阶段之间的关系,逐个求解,并从中找到最优决策序列
在这里插入图片描述

1. 多阶段决策过程

将所给问题的求解过程,恰当的分为若干相互联系的阶段,每一阶段的决策仅依赖于前一阶段的状态,由决策所采取的动作使状态发生转移,成为下一阶段决策的依据。从而,一个决策序列(策略)再不断变化的状态中产生,这个过程称为多阶段决策过程
在这里插入图片描述

  • 阶段变量:用于表示各阶段,如阶段变量k为1~5
  • 状态:描述决策过程当前特征的量
    • s k s_k sk​表示第k个阶段实际取得的状态,如: s k s_k sk​= B 3 B_3 B3​
    • S k S_k Sk​表示第k阶段的可达状态集,如: S 2 = B 1 , B 2 , B 3 S_2={B_1, B_2, B_3} S2​=B1​,B2​,B3​
  • 状态变量:描述过程状态的变量
  • 决策:当求解过程处于某一状态时,做出的选择或决定,从而确定了下一阶段的状态
  • 策略:从第1阶段到最后阶段的决策所构成的序列
  • 状态转移方程:某一阶段状态以及该状态下的决策与下一阶段状态之间函数关系的方程
    • 在最短管道问题中,状态转移方程为:
      在这里插入图片描述
2. 最优性原理

多阶段决策过程的最优决策序列具有如下性质:无论决策过程的初始状态和初始决策是什么,其余的决策都必须相对于初始决策所产生的当前状态,构成一个最优决策序列

  • 最优子结构性质:整个问题的最优解是由各个子问题的最优解构成(使用动态规划的前提)
    在这里插入图片描述

2. 设计思想

1. 动态规划适用条件
  • 满足最优性原理:即具有最优子结构性质,该问题的最优解中也包含其子问题的最优解
  • 重叠子问题:可分解为相互关联的若干子问题,子问题间不独立,子问题的解在下一阶段决策中可能被使用
2. 设计思想

利用最优子结构性质,把整个问题划分成一系列子问题,求各子问题的最优解,然后以自底向上的方式递归地从子问题的最优解构造出整个问题的最优解
在这里插入图片描述

3. 动态规划与分治法
动态规划分治法
相同点都是将子问题分解成若干个子问题,先求子问题的解,然后通过这些子问题的解获得整个问题的解
不同点各个子问题之间具有关联性,对每个子问题仅求解一次,并将其结果“填表”,以后用到时直接存取子问题相互独立,否则重复求解,效率低

在这里插入图片描述

3. 设计步骤

动态规划过程一般求得问题的最优值(即目标函数的极值),如果要求最优解,通常在动态规划过程中记录必要信息,再依据这些信息构造最优解
(1) 划分子问题(分段)

将整个问题分解为若干子问题,找到问题状态,子问题之间具有重叠(关联)关系
(2) 构建状态转移方程(分析)

关联的状态和状态之间相互转换关系(动态规划的关键

(3) 存储状态的值求解(填表)

设计表格(数据结构),以自底向上的方式计算各个子问题的解并填表保存,实现动态规划过程

4. 两种解法(以多段图为例)

在这里插入图片描述

1. 顺序解法

从第1阶段到第k阶段的求解方法(向后处理法)
(1) 划分子问题(分段)
在这里插入图片描述

(2) 构建状态转移方程(分析)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3) 存储状态的值求解(填表)
在这里插入图片描述
(4) 算法设计
在这里插入图片描述

#include <iostream>
#include<vector>

#define MAX 9999								//表示不可达
using namespace std;

//初始化图
/*
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,
它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组
*/
void initGraph(vector<vector<int>>& g, vector<vector<int>>& s) {
	cout << "输入边信息:(顶点a  顶点b  权值w)(输入0结束)" << endl;		//endl表示换行
	int i, j;
	while (cin >> i && i) {					//输入i,且i不为0时
		cin >> j;									//输入j
		cin >> g[i][j];								//g存放权值
	}
	cout << "输入起点:";
	cin >> s[1][0];
	int level;
	cout << "输入中间阶段数:(不含起点和终点层)";
	cin >> level;
	int a = 2;
	for (int i = 1; i <= level; i++) {
		cout << "输入中间第" << i << "阶段的点:(输入0结束)";
		int k, j = 0;
		while (cin >> k && k)						//s存放多段图
			s[a][j++] = k;
		a++;
	}
	cout << "输入终点:";
	cin >> s[a][0];
}

//寻找路径
void way(vector<vector<int>>& g, vector<vector<int>>& s, vector<vector<int>>& f, vector<int>& result) {
	int n = g.size() - 1;								//获取结点数
	int level, i;											//获取总层数(包含起点和在终点)
	for (i = 1; i <= n; i++)
		if (s[i][0] == 0)	break;
	level = i - 1;
	int t = n;
	int start = s[1][0];
	int end = s[level][0];
	for (i = level - 1; i >= 1; i--) {					//阶段
		int j = 0;
		while (s[i][j]) {								//依次遍历每一层所有结点
			int m = 0;									//i+1阶段的点
			f[i][j] = MAX;								
			if (g[s[i][j]][end] == MAX) {		//若s[i][j] -> end没有边
				while (s[i + 1][m] != 0) {			//若下一阶段有点
					if (g[s[i][j]][s[i + 1][m]] != MAX) {   //s[i][j] -> s[i + 1][m]有边
						if (f[i][j] > (f[i + 1][m] + g[s[i][j]][s[i + 1][m]])) {	//若有更短距离
							f[i][j] = f[i + 1][m] + g[s[i][j]][s[i + 1][m]];		//更新当前距离
							result[s[i][j]] = s[i + 1][m];								//保存最短距离路径上的点
							t--;
						}
					}
					m++;
				}
			}
			else {										//若s[i][j] -> end有边
				while (s[i + 1][m] != 0) {			//若下一阶段有点
					if (f[i][j] > (f[i + 1][m] + g[s[i][j]][s[i + 1][m]])) {	//若有更短距离
						f[i][j] = f[i + 1][m] + g[s[i][j]][s[i + 1][m]];		//更新当前距离
						result[s[i][j]] = s[i + 1][m];								//保存最短距离路径上的点
						t--;
					}
					m++;
				}
			}
			j++;
		}
	}
}

//打印
void print(vector<int>& result, vector<vector<int>>& s, vector<vector<int>>& f) {
	int n = result.size() - 1;
	cout << "最短路径为:";
	int t = s[1][0];
	cout << t;
	while (result[t] != s[n][0]) {
		cout << " ->" << result[t];
		t = result[t];
	}
	cout << endl << "最短距离为:" << f[1][0] << endl;
}

void main() {
	int vexNum;
	cout << "输入点的个数:";
	cin >> vexNum;
	vector<vector<int> > graph(vexNum + 1, vector<int>(vexNum + 1, MAX));	//保存边的长度
	vector<vector<int> > s(vexNum + 1, vector<int>(vexNum + 1, 0));			//保存每个阶段的状态
	vector<vector<int> > f(vexNum + 1, vector<int>(vexNum + 1, 0));			//保存该状态下点到终点的距离
	vector<int > result(vexNum + 1, 0);										//保存结果
	initGraph(graph, s);		//初始化图
	way(graph, s, f, result);	//寻找最短路径
	print(result, s, f);			//输出结果
}

(5) 时间复杂度
O ( k + m ) O(k+m) O(k+m),k,m分别为图的边数与段数

2. 逆序解法

从第k段到第1段的解法(从后向前)
(1) 划分子问题(分段)
包含终点T的子图都是一个子问题,子问题的终点是固定的,也就是T点,源点是变化的
(2) 构建状态转移方程(分析)
在这里插入图片描述

标签:状态,决策,问题,vector,阶段,2.1,动态,规划,最优
来源: https://blog.csdn.net/qq_45069496/article/details/122539378

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有