1.确定dp数组(dp table)以及下标的含义
2.确定递推公式
3.dp数组如何初始化
4.确定遍历顺序
5.举例推导dp数组
我们在写动态规划的时候,就是写这几步,一步一步来就ok;而不是一个简简单单的递归公式
比如我们求斐波拉契数列就是,数组下标含义是第几个数,递归公式为一个数是前2个的数的和,数组的初始化就是第0个数是0,第一个数是1,那我们是前面几个那便利顺序就应该是从前往后,然后就可以把这个写出来
a[0]=0;
a[1]=1;
for(i=2;i<=n;i++)
{
a[i]=a[i-1]+a[i-2];
}
题目
# [NOIP2002 普及组] 过河卒
## 题目描述
棋盘上 $A$ 点有一个过河卒,需要走到目标 $B$ 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 $C$ 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,$A$ 点 $(0, 0)$、$B$ 点 $(n, m)$,同样马的位置坐标是需要给出的。
![](https://cdn.luogu.com.cn/upload/image_hosting/vg6k477j.png)
现在要求你计算出卒从 $A$ 点能够到达 $B$ 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
## 输入格式
一行四个正整数,分别表示 $B$ 点坐标和马的坐标。
## 输出格式
一个整数,表示所有的路径条数。
## 样例 #1
### 样例输入 #1
```
6 6 3 3
```
### 样例输出 #1
```
6
```
## 提示
对于 $100 \%$ 的数据,$1 \le n, m \le 20$,$0 \le$ 马的坐标 $\le 20$。
**【题目来源】**
NOIP 2002 普及组第四题
我们按照上面5步来,下标含义是该点的位置,递归公式为fa[i][j]=fa[i-1][j]+fa[i][j-1];初始化应该就是fa【1】【1】就是1,我们从1,1开始方便一些,遍历数组是前面两个推出后面的,那遍历就应该是从前往后,按照着几步,把代码写出来就ok
#include <stdio.h>
long long fa[100][100];//棋盘0就是ok,1就是不ok
int pan[100][100];
int ma[9]={0,1,2,2,1,-1,-2,-2,-1};//x坐标
int ma1[9]={0,2,1,-1,-2,-2,-1,1,2};//y坐标
int main()
{
int i,j;
int n,m,x,y;
scanf("%d%d%d%d",&n,&m,&x,&y);//坐标
n+=2;m+=2;x+=2;y+=2;
fa[2][1]=1;//出口
for(i=1;i<=9;i++)
{
pan[x+ma[i]][y+ma1[i]]=1;
}
for(i=2;i<=n;i++)
{
for(j=2;j<=m;j++)
{
if(pan[i][j]) continue;//找到是1就过
fa[i][j]=fa[i-1][j]+fa[i][j-1];
//printf("%lld %d %d\n",fa[i][j],i,j);
}
}
printf("%lld",fa[n][m]);
}
# [USACO1.5][IOI1994]数字三角形 Number Triangles
## 题目描述
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
```cpp
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
```
在上面的样例中,从 $7 \to 3 \to 8 \to 7 \to 5$ 的路径产生了最大
## 输入格式
第一个行一个正整数 $r$ ,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
## 输出格式
单独的一行,包含那个可能得到的最大的和。
## 样例 #1
### 样例输入 #1
```
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
```
### 样例输出 #1
```
30
```
## 提示
【数据范围】
对于 $100\%$ 的数据,$1\le r \le 1000$,所有输入在 $[0,100]$ 范围内。
题目翻译来自NOCOW。
USACO Training Section 1.5
IOI1994 Day1T1
这道题目我们要是从最上面那个数来求的话,那时间太久了,我们可以从下面求上去,就欧克啦,思路我就不写了,看代码吧
#include <stdio.h>
int max(int x,int y)
{
if(x>y) return x;
else return y;
}
int main()
{
int i,j,teap;
int n;
int a[1001][1001];
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<=i;j++)
{
scanf("%d",&a[i][j]);
}
}
for(i=n-1;i>=1;i--)
{
for(j=1;j<=i;j++)
{
teap=max(a[i+1][j],a[i+1][j+1]);
a[i][j]=a[i][j]+teap;
}
}
printf("%d",a[1][1]);
}
okok下班下班