刷题Day14基础DP之过河卒

前言

 本题是一道基础的动态规划问题,但是因为某些测试的数据最终的结果可能大于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[n1][m]+a[n][m1]
 但是这里还要一个控制每个点的马,而按照马走的规则,若记马所在点为(H1,H2),则所有满足条件 ( x − H 1 ) 2 + ( y − H 2 ) 2 = 5 (x-H1)^2+(y-H2)^2=5 (xH1)2+(yH2)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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值