题目描述
棋盘上 AA 点有一个过河卒,需要走到目标 BB 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 CC 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示, AA 点 (0, 0)(0,0) 、 BB 点 (n, m)(n,m) ( nn , mm 为不超过 2020 的整数),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 AA 点能够到达 BB 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入输出格式
输入格式:
一行四个数据,分别表示 BB 点坐标和马的坐标。
输出格式:
一个数据,表示所有的路径条数。
输入输出样例
说明
结果可能很大!
思路过程
第一感觉,就想用深度优先搜索做,然后里面wa最后还超时一发。。。后面自己仔细想了一下,如果深度优先和广度优先,那么肯定是不对的,因为无论是深搜还广度优先搜索,最坏结果都是需要遍历每个点,这样遍历每个点复杂度是2^n,稳稳的超时。。。后来想想,其实不妨这样想,每个点只可能从上面和左边推过来,这样就从第一个点往后推即可,转移方程:
dp[i][j]=dp[i-1][j]+dp[i][j-1]
这应该是递推,不能算是动态规划,最后提醒一点,在判断马控制的位置需要判断一下边界条件不然。。。会被坑(下次一定要记住)
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; int mv[2][10]={{0,-2,-2,-1,-1,1,1,2,2},{0,1,-1,2,-2,2,-2,1,-1}};//用二维数值写方向很方便 long long dp[25][25]; bool visit[25][25]; int main(){ int nx,ny,hx,hy; scanf("%d%d%d%d",&nx,&ny,&hx,&hy); memset(dp,0,sizeof(dp)); memset(visit,0,sizeof(visit)); for(int i=1;i<=8;i++){ if (hx+mv[0][i]>=0 && hx+mv[0][i]<=nx && hy+mv[1][i]>=0 && hy+mv[1][i]<=ny) visit[hx+mv[0][i]][hy+mv[1][i]]=1; } visit[hx][hy]=1; dp[0][0]=1; for(int i=0;i<=nx;i++){ for(int j=0;j<=ny;j++){ if (i) dp[i][j]+=dp[i-1][j]; if (j) dp[i][j]+=dp[i][j-1]; dp[i][j]*=!visit[i][j]; } } printf("%lld",dp[nx][ny]); return 0; }