动态规划

Posted morui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划相关的知识,希望对你有一定的参考价值。

斐波那契数列

F【0】=1,F【1】=1         -> 边界条件

F【N】=F【N-1】+F【N-2】     -> 转移方程

F【0】、F【1】……F【N】   ->状态

 

书写代码方法:

顺着推/逆着推/记忆化搜索

 

代码示例:

#include<iostream>
using namespace std;

int n,f[10086];

int main(){
    
    /*
     *顺着推
     */ 
    cin>>n;
    f[0]=1;
    f[1]=1;
    
    for( int i=2 ; i<=n ; ++i ){
        f[i]=f[i-1]+f[i-2];
    }
    
    cout<<f[n];
    
    /*
     *逆着推
     */ 
    cin>>n;
    f[0]=1;
    f[1]=1;
    
    for( int i=0 ; i<n ; ++i ){
        f[i-1] += f[i];
        f[i-2] += f[i];
    }
    
    cout<<f[n];
    
    return 0;
} 

 

记忆化搜索:

#include<iostream>
using namespace std;
#define N 10086

int n;
int f[N];
bool vis[N];

/*
 *搜索
 */ 
int dfs( int n ){
    
    if( n==0 ) return 1;
    if( n==1 ) return 1;
    
    return dfs(n-1)+dfs(n-2);
}//O( f(n) )

/*
 *记忆化搜索 
 */
int dfs( int n ){
    
    if( n==0 ) return 1;
    if( n==1 ) return 1;
    if( vis(n) ) return f[n];
    
    vis[n] = 1;
    f[n] = dfs(n-1)+dfs(n-2);
    
    return f[n];
}//O(n) 

int main(){
    
    cin>>n;
    cout<<dfs(n)<<endl;
    
    return 0;
}

 

 

常见动态规划种类:

数位/树形/状压/区间/其他

(插头/博弈论)

 

数位DP:

读入两个正整数,L,R ,在【L,R】中,有多少个数?

[L~R] -> [0~R] - [0~(L-1)]

[0,X] -> Xn Xn-1 Xn-2 ...... Xn-n
0<=V<=X -> Vn Vn-1 Vn-2 ...... Vn-n

1、 XnXn-1Xn-2 > VnVn-1Vn-2 Vn∈[0,9];
2、 XnXn-1Xn-2 = VnVn-1Vn-2 Vn∈[0,Xn];

状态
f[i][j] -> 该状态方案数
i -> 已填好的第i位
j -> 0/1 j=0 XnXn-1Xn-2 > VnVn-1Vn-2
j=1 XnXn-1Xn-2 = VnVn-1Vn-2

转移方程
枚举i-1位填什么
f[i][j]=f[i-1][j]

边界
Xn+1 = 0 ; Vn+1 = 0

 

#include<iostream>
using namespace std;
#define N 10086

int l,r,z[N];
int f[N][2];

int solve( int x ){
    int n=0;
    while(x){
        z[n] = x%10;
        x/=10;
        n++;
    }
    n--;
    
    memset( f,0,sizeof(f));
    f[n+1][1] = 1;
    
    for( int i=n ; i>=0 ; --i ){
        for( int j=0 ; j<=1 ; ++j ){
            if( b==0 ){
                for( int k=0 ; k<=9 ; ++k ){
                    f[i][0] += f[i+1][0];
                }
            }
            else{
                for(int k=0 ; k<=z[a] ; ++k ){
                    if( k==z[a] ) f[a][1] += f[a+1][1];
                    else f[a][0] += f[a+1][1];
                }
            }
        }
    }
    
    return f[0][0] + f[0][1];
}

int main(){

    cin>>l>>r;
    
    cout<< solve(r) - solve(l-1) <<endl;
    return 0;
}

 

以上是关于动态规划的主要内容,如果未能解决你的问题,请参考以下文章

是否可以动态编译和执行 C# 代码片段?

动态规划_线性动态规划,区间动态规划

应对笔试手写代码,如何准备动态规划?

应对笔试手写代码,如何准备动态规划?

应对笔试手写代码,如何准备动态规划?

算法动态规划 ⑤ ( LeetCode 63.不同路径 II | 问题分析 | 动态规划算法设计 | 代码示例 )