动态规划(一)基础递推

动态规划DP(一)

首先,我们知道在使用动态规划,也就是DP解题时,我们常会开一个数组DP,用来保存所有状态时的解。

递推,顾名思义,一步一步推导。

因此,在做该类型题目时,DP数组的每一个状态的值,都是由前面的值所推导出来的,可以用到min,max,和 等等。

解题时,一般先赋初始值,再寻找状态,算出状态转移方程后,再根据具体例题一步步推导,最终得到所要答案。

这也是入门DP以来,最先遇到的一类题型,如数字三角形求最大和问题。

例题:洛谷P1002 过河卒

题目描述:

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,A(0, 0)、B(n, m)(n, m为不超过20的整数),同样马的位置坐标是需要给出的。

现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

输入格式

一行四个数据,分别表示B点坐标和马的坐标。

输出格式

一个数据,表示所有的路径条数。

输入输出样例

输入 #1
6 6 3 3
输出 #1
6

说明/提示

结果可能很大!

题解:

首先仔细读题。

读完题后我们知道马所控制的点都是无法通过的

先找到属性,从题目中可知是格子的行和列,用这个来定位dp数组

首先先给dp[ 0 ][ 0 ]赋一个初始值1,表示到dp[ 0 ][ 0 ]有一条路

又从题目中可以知道,卒每次只能向右走,或者向下走,因此可以简单地得出状态转移方程:dp[ i ] [ j ] = dp[ i-1 ] [ j ] + dp[ i ] [ j-1 ]

再根据这个公式来推导dp数组中每一个状态的值

要注意的点有两个:

1、不能越数组的界。

因此在推导的过程中,把数组边缘的点直接赋值,不通过状态转移方程来推导。

2、说明中写了答案可能会很大

因此这边我们用long long来保存答案。

代码:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int a[25][25];
 6 long long dp[25][25]; //可能爆内存所以开long long 
 7 int n, m;
 8 int t, k;
 9 
10 int main()
11 {
12     cin >> n >> m;
13     cin >> t >> k;
14     
15     a[t][k] = -1; //标记马的控制点 
16     a[t-1][k+2] = -1;
17     a[t-2][k+1] = -1;
18     a[t-1][k-2] = -1;
19     a[t-2][k-1] = -1;
20     a[t+1][k-2] = -1;
21     a[t+2][k-1] = -1;
22     a[t+1][k+2] = -1;
23     a[t+2][k+1] = -1;
24     
25     dp[0][0] = 1;
26     
27     for(int i = 0; i <= n; i++)
28     {
29         for(int j = 0; j <= m; j++)
30         {
31             if(a[i][j] == -1) //判断为马的控制点,则该店路径条数为0 
32             {
33                 dp[i][j] = 0;
34                 continue;    
35             }
36             if(i == 0 && j == 0) continue; //第一行第一个点 
37             if(i == 0) //第一行的路径条数 
38             {
39                 dp[i][j] = dp[i][j-1];    
40                 continue;
41             }
42             if(j == 0) //第一列的路径条数 
43             {
44                 dp[i][j] = dp[i-1][j];
45                 continue;
46             }
47             dp[i][j] = dp[i-1][j] + dp[i][j-1]; //状态转移方程推导每个点的路径条数 
48         }
49     }
50     cout << dp[n][m]; 
51 }

但是,递推本身和动态规划并不是同一种东西。

每个阶段只有一个状态->递推;
每个阶段的最优状态都是由上一个阶段的最优状态得到的->贪心;
每个阶段的最优状态是由之前所有阶段的状态的组合得到的->搜索;
每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到而不管之前这个状态是如何得到的->动态规划。

猜你喜欢

转载自www.cnblogs.com/yramvj/p/11294938.html
今日推荐