一、简介
动态规划适合与解决最优问题,求最大值最小值等,可以显著降低时间复杂度。
1 动态规划算法思想:
一个模型: 多阶段决策最优解模型。
三个特征:
最优子结构:文图的最优解包含子问题的最优解;
无后效性:推导后面阶段的状态时,只关心前面阶段的状态值,不关心状态时怎么来的,某阶段的状态决定之后不受之后阶段状态的影响。
重复子问题:不同的决策序列,到达某个相同的阶段可能会产生重复的状态。
解决动态规划问题的解题总结:
状态转移表法: 将解决问题转化成状态表,分阶段填充状态表的每个状态。
解题思路:回溯算法实现 - 定义状态 - 画递归树 - 找重复子问题 - 画状态转移表 - 根据递推关系填表 - 将填表过程翻译成代码。
状态转移方程法: 某个问题如何通过子问题来递归求解,也就是所谓的最优子结构。根据最优子结构,写出递归公式,也就是所谓的状态转移方程,代码的实现可以用递归加“备忘录”或者是迭代递推。
大致思路可以概括为,找最优子结构 - 写状态转移方程 - 将状态转移方程翻译成代码。
0-1背包问题:
回溯算法的思路:
穷举搜索所有可能的装法,然后找出满足条件的最大值。当计算有重复的时候采用“备忘录”的方法记录已经计算好的值,就可以避免冗余计算。
2 动态规划解决思路:
将问题分解为多个阶段,每个阶段对应一个决策。我们记录每一个阶段可达的状态集合(去掉重复的),然后通过当前阶段的状态集合,来推导下一个阶段的状态集合,动态地往前推进。
贪心,分治,回溯,动态规划算法的比较:
贪心算法: 是动态规划算法的一种特殊情况。它解决问题起来更加高效,代码实现也更加简洁。不过,它可以解决的问题也更加有限。它能解决的问题需要满足三个条件,最优子结构、无后效性和贪心选择性;
分治算法: 解决的问题尽管大部分也是最优解问题,但是,大部分都不能抽象成多阶段决策模型;
回溯算法: 相当于穷举搜索。穷举所有的情况,然后对比得到最优解。不过,回溯算法的时间复杂度非常高,是指数级别的,只能用来解决小规模数据的问题。对于大规模数据的问题,用回溯算法解决的执行效率就很低了;
动态规划: 比回溯算法高效,需要满足三个特征,最优子结构、无后效性和重复子问题。分治算法不能有重复的子问题,动态规划之所以高效,就是因为回溯算法实现中存在大量的重复子问题。
二、源代码
unction varargout = FindSP(varargin)
%寻找最短路径,GUI界面显示
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @FindSP_OpeningFcn, ...
'gui_OutputFcn', @FindSP_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before FindSP is made visible.
function FindSP_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to FindSP (see VARARGIN)
% Choose default command line output for FindSP
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes FindSP wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = FindSP_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% 计算最短路径,并显示在界面上
if(handles.dimension==2) %二维
[handles.SP,handles.data]=findSP_2D(handles.A); %求最短路径,handles.SP为最小和,handles.data为最短路径
set(handles.text1,'string',num2str(handles.SP));%在text1(文本框)中显示最小和
%显示最短路径到Excel中
data = mat2cell(handles.A,ones(1,size(handles.A,1)),ones(1,size(handles.A,2)));
n=size(handles.data,1);
for i=1:n
j=handles.data(i,1);
k=handles.data(i,2);
data{j,k}=['<html><table><tr><td width=100 bgcolor="yellow">','<FONT face="Times New Roman"size="4"color=black">',num2str(data{j,k},'%5d'), '</table></html>'];
end
set(handles.uitable1,'data',data); %显示最短路径
get(handles.uitable1,'ColumnWidth')
guidata(hObject, handles);
end
if(handles.dimension==3) %三维
[handles.SP,handles.data]=findSP_3D(handles.A); %求最短路径,handles.SP为最小和,handles.data为最短路径
[m,n,p]=size(handles.A);
set(handles.text1,'string',num2str(handles.SP));%在text1(文本框)中显示最小和
%动态显示路径
axes(handles.axes1);
h = plot3(1,1,1);
axis([1,m,1,n,1,p]);
grid on
for k = 1:numel(handles.data(:,1))
set(h,'XData',handles.data(1:k,1),'YData',handles.data(1:k,2),'ZData',handles.data(1:k,3));
drawnow;
axis([1,m,1,n,1,p]);
pause(0.3);
end
guidata(hObject, handles);
end
% --------------------------------------------------------------------
function Untitled_1_Callback(hObject, eventdata, handles)
% hObject handle to Untitled_1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% --------------------------------------------------------------------
function Untitled_2_Callback(hObject, eventdata, handles)
% 打开文件对话框读取二维矩阵(txt格式)
filename=uigetfile('.txt');
fid=fopen(filename);
handles.A=readData(fid);
handles.dimension=2; %标志维度,2表示二维
fclose(fid);
set(handles.uitable1,'visible','on','data',handles.A); %原矩阵显示在表格上
axes(handles.axes1);cla reset; %清空坐标轴中的路径信息
set(handles.axes1,'visible','off');%隐藏显示三维路径的坐标轴
set(handles.text1,'string',' ');%清空text1(文本框)中显示的最小和
guidata(hObject, handles);
% --------------------------------------------------------------------
function Untitled_5_Callback(hObject, eventdata, handles)
% hObject handle to Untitled_5 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% --------------------------------------------------------------------
function Untitled_3_Callback(hObject, eventdata, handles)
% 建立随机矩阵
%弹出输入对话框用于确定随机矩阵的大小,矩阵元素取值范围等信息
prompt={'行数','列数','矩阵元素取值范围'};
title='随机矩阵参数设置';
lines=[1 1 1];
def={'6','6','0 10'};
answer=inputdlg(prompt,title,lines,def);
m=str2double(answer{1});
n=str2double(answer{2});
range=str2num(answer{3});
min=range(1);max=range(2);
handles.A=round((rand(m,n))*(max-min)+min); %原矩阵
handles.dimension=2; %二维
set(handles.uitable1,'visible','on','data',handles.A); %原矩阵显示在表格上
axes(handles.axes1);cla reset; %清空坐标轴中的路径信息
set(handles.axes1,'visible','off');%隐藏显示三维路径的坐标轴
set(handles.text1,'string',' ');%清空text1(文本框)中显示的最小和
guidata(hObject, handles);
% --------------------------------------------------------------------
function Untitled_4_Callback(hObject, eventdata, handles)
%保存路径结果(二维)
fid=fopen('result_2D.txt','w');
fprintf(fid,'最小和:%d\r\n最短路径: (行号,列号)\r\n',handles.SP);
[m,n]=size(handles.data);
for i=1:m
fprintf(fid,'(%d,%d)\r\n',handles.data(i,1),handles.data(i,2));
end
三、运行结果
四、备注
版本:2014a