动态规划DP入门笔记

发布时间 2023-07-13 16:31:19作者: FinderHT

动 态 规 划

以斐波那契数列 为例:

\(f_i\) 状态
\(f_i = f_{i-1}+f_{i-2}\) 转移方程
\(f_0 = 0\) , \(f_1 = 1\) 初始化

dp的实现方法一般有三种,其中的两种(最重要的)如下

#include<bits/stdc++.h>
using namespace std;
int f[200010];
signed main(){
	int n;
	scanf("%d",&n);
	/*
	f[1]=1;
	f[0]=0;
	for(int i=2;i<=n;i++)
		f[i]=f[i-1]+f[i-2];//1.用别人的值去维护自己的值 
	printf("%d\n",f[n]);
	memset(f,0,sizeof(f));
	*/
	f[1]=1;
	f[0]=0;
	for(int i=0;i<=n;i++){//2.用自己的值去维护自己的值 
		f[i+1]+=f[i];
		f[i+2]+=f[i]; 
	}
	printf("%d",f[n]);
	return 0;
} 

第三种

#include<bits/stdc++.h>
using namespace std;
int f[200010];//f[i]表示斐波那契数列的第i项 
bool g[200010];//g[i]表示斐波那契数列第i项有没有求出来 
int n;
int dfs(int n){//求斐波那契数列第i项 
	if(n==0)return 0;
	if(n==1)return 1;
	if(g[n])return f[n];
	g[n]=true;
	f[n]=dfs(n-1)+dfs(n-2);//记忆化搜索 
	return f[n];
} 
signed main(){
	scanf("%d",&n);
	printf("%d",dfs(n));
	return 0;
} 

最大上升子序列(化身P党):

uses math;
var f:array[0..5005] of longint;
var a:array[0..5005] of longint;
var n,i,j,ans:longint;
begin
	readln(n);
	for i:=1 to n do begin
		read(a[i]);
	end;
    f[1]:=1;
	for i:=2 to n do begin
		for j:=1 to i-1 do begin  
			if a[j]<a[i] then begin
				f[i]:=max(f[i],f[j]);
			end;
		end;
        f[i]:=f[i]+1;
	end;
	ans:=0;
	for i:=1 to n do begin
		ans:=max(f[i],ans);
	end;
	writeln(ans);
end.