前言
本题是一道基础的动态规划问题,但是因为某些测试的数据最终的结果可能大于int能表示的范围,因此本题做的时候记得开long long int 类型。
先放题目位置;P1002 [NOIP2002 普及组] 过河卒
解题思路:
比较明显的DP思路。因为棋盘上的卒想要从(0,0)走到(n,m),最终一共是两种情况,即走到(n-1,m)处然后向右走一步;走到(n,m-1)处然后向下走一步。若记
a
[
n
]
[
m
]
a[n][m]
a[n][m]为过河卒走到(n,m)处一共有的方法数,则朴素来看有如下递推关系:
a
[
n
]
[
m
]
=
a
[
n
−
1
]
[
m
]
+
a
[
n
]
[
m
−
1
]
a[n][m]=a[n-1][m]+a[n][m-1]
a[n][m]=a[n−1][m]+a[n][m−1]
但是这里还要一个控制每个点的马,而按照马走的规则,若记马所在点为(H1,H2),则所有满足条件
(
x
−
H
1
)
2
+
(
y
−
H
2
)
2
=
5
(x-H1)^2+(y-H2)^2=5
(x−H1)2+(y−H2)2=5的点(x,y)都是控制点,而对于控制点,则没有如此的表达式,若
(
H
x
,
H
y
)
(H_x,H_y)
(Hx,Hy)为控制点则
a
[
H
x
]
[
H
y
]
=
0
a[H_x][H_y]=0
a[Hx][Hy]=0。
初始化的时候,其实只需要初始化第0行和第0列,且每一位按照意义置为1;但是一点遇到控制点,控制点以后所有位置对应值就应该置为0。最后给出我的AC代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
long long int n,m,H1,H2;
scanf("%lld%lld%lld%lld",&n,&m,&H1,&H2);
long long int a[n+1][m+1],i,j;
for(i=0;i<=n;i++){
if(abs(i-H1)*abs(i-H1)+abs(0-H2)*abs(0-H2)==5){
break;
}else if(i==H1&&0==H2){
break;
}
a[i][0]=1;
}
while(i<=n){
a[i][0]=0;
i++;
}
for(j=0;j<=m;j++){
if(abs(j-H2)*abs(j-H2)+abs(0-H1)*abs(0-H1)==5){
break;
}else if(0==H1&&j==H2){
break;
}
a[0][j]=1;
}
while(j<=m){
a[0][j]=0;
j++;
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(abs(i-H1)*abs(i-H1)+abs(j-H2)*abs(j-H2)==5){
a[i][j]=0;
}else if(i==H1&&j==H2){
a[i][j]=0;
}else{
a[i][j]=a[i-1][j]+a[i][j-1];
}
}
}
printf("%lld",a[n][m]);
return 0;
}