最簡單和經典的一維和線性dp:
斐波那契和連續最大和問題:
把多階段過程轉化爲一系列單階段問題,利用各階段之間的關係,逐個求解,創立了解決這類過程優化問題的新方法——動態規劃。
暴力遞歸:
1,把問題轉化爲規模縮小了的同類問題的子問題
2,有明確的不需要繼續進行遞歸的條件(base case)
3,有當得到了子問題的結果之後的決策過程
4,不記錄每一個子問題的解。
而我們需要把這種遞歸思路轉換爲動態規劃
遞歸到動規的一般轉化方法
1 遞歸函數有n個參數,就定義一個n維的數組
2 數組的下標是遞歸函數參數的取值範圍
3 數組元素的值是遞歸函數的返回值,這樣就可以從邊界值開始, 逐步填充數組,相當於計算遞歸函數值的逆過程。
1. 將原問題分解爲子問題
把原問題分解爲若干個子問題,子問題和原問題形式相同或類似,只不過規模變小了。子問題都解決,原問題即解決 子問題的解一旦求出就會被保存,所以每個子問題只需求 解一次。
2.確定狀態 整個問題的時間複雜度是狀態數目乘以計算每個狀態所需時間。
3.確定一些初始狀態(邊界狀態)的值
4. 確定狀態轉移方程
定義出什麼是“狀態”,以及在該“狀態”下的“值”後,就要找出不同的狀態之間如何遷移――即如何從一個或多個“值”已知的 “狀態”,求出另一個“狀態”的“值”(遞推型)。狀態的遷移可以用遞推公式表示,此遞推公式也可被稱作“狀態轉移方程”。
//斐波那契
class Solution {
public:
int Fibonacci(int n) {
if(n==0)
return 0;
if(n==1||n==2)
return 1;
int first=1,second=1;
for(int i=2;i<n;i++)
{
int temp=second;
second=first+second;
first=temp;
}
return second;
}
};
//連續最大和
#include <iostream>
#include <vector>
using namespace std;
int fun(vector<int> & v)
{
int max=v[0];
int ret=max;
for(int i=1;i<v.size();i++)
{
max=std::max(max,0)+v[i];
ret=std::max(ret,max);
}
return ret;
}
int main()
{
int n;
while(cin>>n)
{
vector<int> v;
v.reserve(n);
while(n--)
{
int num;
cin>>num;
v.push_back(num);
}
cout<<fun(v)<<endl;
}
}