动态规划算法通常用于求解具有某种最优性质的问题 这类问题中, 可能会有许多可行解. 每一个解都对应一个值, 希望找到具有最优值的解

  • 动态规划算法与分治法类似, 其基本思想也是将待求解问题分解成若干个子问题, 先求解子问题, 然后从这些子问题的解得到原问题的解.
  • 与分治法不同的是, 适合动态规划求解的问题, 经分解得到的子问题往往不是互相独立的. 用分治法得到的子问题数目太多, 有些子问题被重复计算了很多次, 如果能保存已解决的子问题的答案, 而在需要的时候找出已求得的答案, 就可以避免重复大量的计算

动规五部曲

  • 理解dp数组的含义,以及下标的含义
  • 得到递推公式
  • dp数组如何初始化
  • 确定遍历顺序
  • 当出现问题了,要学会打印dp数组


过河卒

❓ 为什么不能用广度搜索

  • 实测20,20的时候跑不出来, 仔细想想, 因为结果要的是到终点的路径条数, 意味着每次经过一个点都要重复计算, 因为每重复算都是来自新的一条路, 所以考虑能不能不要重复计算

解题思路: 如果将每个点有个数组, 包含的是到这个点的路径条数有多少会怎样?

#include <bits/stdc++.h>
using namespace std;
 
const int MAXN=21;
int dp[MAXN][MAXN];
int vis[MAXN][MAXN];
int zhx,zhy,mx,my;
 
int mal[][2]={
    /*{0,0},*/{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,1},{-2,-1}
};
 
// bool iszhuang(int x,int y){
//     for(int i=0;i<9;i++){
//         if(x==mx+mal[i][0] && y==my+mal[i][1])
//             return true;
//     }
//     return false;
// }
 
int main(){
 
    cin>>zhx>>zhy>>mx>>my;
 
    vis[mx][my]=1;
    for(int i=0;i<8;i++){
        int xt=mx+mal[i][0];
        int yt=my+mal[i][1];
        if(xt>=0 && yt>=0 && xt<=zhx && yt<=zhy) vis[xt][yt]=1;
    }
 
 
    dp[0][0]=1;
    for(int i=0;i<=zhx;i++){
        for(int j=0;j<=zhy;j++){
            // if(!iszhuang(i,j)){
            //     if(i==0 && j!=0){
            //         dp[i][j]+=dp[i][j-1];
            //         continue;
            //     }else if(i!=0 && j==0){
            //         dp[i][j]+=dp[i-1][j];
            //         continue;
            //     }else if(i!=0 && j!=0){
            //         dp[i][j]+=dp[i-1][j]+dp[i][j-1];
            //     }
            // }else{
            //     dp[i][j]=0;
            // }
            if(i) dp[i][j]+=dp[i-1][j];
            if(j) dp[i][j]+=dp[i][j-1];
            if(vis[i][j]) dp[i][j]=0;
        }
    }
    cout<<dp[zhx][zhy];
 
    return 0;
}

最后一段注释, 考虑一下, 0不0的都可以用这样的语句简单完成