動態規劃

基本模型

多階段決策過程的最優化問題。
含有遞推的思想以及各類數學原理(加法原理,乘法原理等等)。
在現實生活中,有一類活動的過程,因爲它的特殊性,可將過程分紅若干個互相聯繫的階段,在它的每一階段都須要做出決策,從而使整個過程達到最好的活動效果。固然,各個階段決策的選取不是任意肯定的,它依賴於當前面臨的狀態,又影響之後的發展,當各個階段決策肯定後,就組成一個決策序列,於是也就肯定了整個過程的一條活動路線
 
這種把一個問題看做是一個先後關聯具備鏈狀結構的多階段過程就稱爲多階段決策過程,這種問題就稱爲多階段決策問題。
 

基本思想

動態規劃算法一般用於求解具備某種最優性質的問題。在這類問題中,可能會有許多可行解。每個解都對應於一個值,咱們但願找到具備最優值的解。動態規劃算法與 分治法相似,其基本思想也是將待求解問題分解成若干個子問題,先求解子問題,而後從 這些子問題的解獲得原問題的解。與分治法不一樣的是,適合於用動態規劃求解的問題,經分解獲得子問題每每不是互相獨立的。若用分治法來解這類問題,則分解獲得的子問題數目太多,有些子問題被重複計算了不少次。若是咱們可以保存已解決的子問題的答案,而在須要時再找出已求得的答案,這樣就能夠避免大量的重複計算,節省時間。咱們能夠用一個表來記錄全部已解的子問題的答案。無論該子問題之後是否被用到,只要它被計算過,就將其結果填入表中。這就是動態規劃法的基本思路。具體的動態規劃算法多種多樣,但它們具備相同的填表格式。
 

基本結構

多階段決策問題中,各個階段採起的 決策,通常來講是與時間有關的,決策依賴於當前狀態,又隨即引發狀態的轉移,一個決策序列就是在變化的狀態中產生出來的,故有「動態」的含義,稱這種解決多階段決策最優化問題的方法爲動態規劃方法。
 

基本模型

根據上例分析和動態規劃的基本概念,能夠獲得動態規劃的基本模型以下:
(1)肯定問題的決策對象。 (2)對決策過程劃分階段。 (3)對各階段肯定 狀態變量。 (4)根據狀態變量肯定費用 函數和目標函數。 (5)創建各階段狀態變量的轉移過程,肯定狀態轉移方程。
狀態轉移方程的通常形式:
通常形式: U:狀態; X:策略
  順推:f[Uk]=opt{f[Uk-1]+L[Uk-1,Xk-1]} L[Uk-1,Xk-1]: 狀態Uk-1經過策略Xk-1到達狀態Uk 的費用 初始f[U1];結果:f(Un)
倒推:
  f[Uk]=opt{f[Uk+1]+L[Uk,Xk]}
  L[Uk,Xk]: 狀態Uk經過策略Xk到達狀態Uk+1 的費用
  初始f[Un];結果:f(U1)

適用條件

任何思想方法都有必定的侷限性,超出了特定條件,它就失去了做用。一樣,動態規劃也並非萬能的。適用動態規劃的問題必須知足最優化原理和無後效性。
1. 最優化原理(最優子結構性質) 最優化原理可這樣闡述:一個最優化策略具備這樣的性質,不論過去狀態和決策如何,對前面的決策所造成的狀態而言,餘下的諸決策必須構成最優策略。簡而言之,一個最優化策略的子策略老是最優的。一個問題知足最優化原理又稱其具備最優子結構性質。
2. 無後效性將各階段按照必定的次序排列好以後,對於某個給定的階段狀態,它之前各階段的狀態沒法直接影響它將來的決策,而只能經過當前的這個狀態。換句話說,每一個狀態都是過去歷史的一個完整總結。這就是無後向性,又稱爲無後效性。
3.子問題的重疊性 動態規劃將原來具備指數級時間複雜度的 搜索算法改進成了具備多項式時間複雜度的算法。其中的關鍵在於解決冗餘,這是動態規劃算法的根本目的。動態規劃實質上是一種以空間換時間的技術,它在實現的過程當中,不得不存儲產生過程當中的各類狀態,因此它的空間複雜度要大於其它的算法。
 

基本步驟

《1》劃分階段:按照問題的時間或空間特徵,把問題分爲若干個階段。注意這若干個階段必定要是有序的或者是可排序的(既無後效性),不然問題就沒法用動態規劃求解。算法

《2》選擇狀態:將問題發展到各個階段時所處於的各類客觀狀況用不一樣的狀態表示出來。固然,狀態的選擇要知足無後效性。函數

《3》肯定決策並寫出狀態轉移方程:之因此把這兩步放在一塊兒,是由於決策和狀態轉移有着自然的聯繫,狀態轉移就是根據上一階段的狀態和決策來導出本階段的狀態。因此,若是咱們肯定了決策,狀態轉移方程也就寫出來了。但事實上,咱們經常是反過來作的,根據相鄰兩段的各狀態之間的關係來肯定決策。優化

《4》寫出規劃方程(包括邊界條件):動態規劃的基本方程就是規劃方程的通用形式化表達式。通常來講,只要階段、狀態、決策和狀態轉移肯定了,這一步仍是比較簡單的。spa

 

實例

/*

一、問題描述
	如圖,既定一個具備N層數字三角形,從頂至底有多條路徑,每一步可沿左斜線向下或沿右斜線向下,路徑所通過的數字之和爲路徑得分,
	請求出最小路徑得分。
	
					2 
				6		2
			1		8		4
		1		5		6		8

*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#define M 10000
using namespace std;

typedef struct Node
{
	int pow,score;
}Node;


Node* head[M];

int main()
{
	int n,i,j;
	Node *a,*b;
	printf("請輸入三角形行數:");
	scanf("%d",&n);
	
	memset(head,NULL,sizeof(head));
	for(i=1;i<=n;i++)
	{
		a=(Node*)malloc((i+1)*sizeof(Node));
		for(j=1;j<=i;j++)
		{
			scanf("%d",&a[j].pow);
			a[j].score=a[j].pow;
		}
		head[i]=a;
	}
	    //初始化最底層得分
	a=head[n];
	for(i=1;i<=n;i++){
		a[i].score=a[i].pow;
	}    //從倒數第二層開始進行動態規劃
	for(i=n-1;i>0;i--)
	{
		a=head[i];
		b=head[i+1];
		for(j=1;j<=i;j++)
		{
			a[j].score += min(b[j].score,b[j+1].score);//取左右路徑中得分最小的
		}
	}
	
	printf("最少得分:%d\n",head[1][1].score);
	
/*	for(i=1;i<=n;i++)
	{
		a=head[i];
		for(j=1;j<=i;j++)
		{
			printf("%d ",a[j].pow);
		}
		printf("\n");
	}
*/
	
	
	return 0;
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息