思路
设 \(dp_{i,j}\) 表示第 \(i\) 行 \(j\) 列卒走到这里有多少种方式。
卒是可以向右和下走,所以到这个点只能从左或上来,不难得出转移公式:\(dp_{i,j} = dp_{i-1,j}+dp_{i,j-1}\)。
如果马在这个点上或者说马能到这个点上,那么卒不能到这个点,也就是卒到这个点的方式为 \(0\)。
如何判断马能不能到这个点呢?我们需要一个方向数组,马能走八个方向,依次枚举这八个点是不是当前点即可。
以上就是全部思路,但是还要注意一下几点:
- \(dp_{0,0}\) 赋值为 \(1\),初始化。
- 在转移过程中会数组越界,所以需要判断。
- 转移时如果当前点是 \((0,0)\) 则不进行转移,因为这是初始点,已经有值了。
AC CODE
#include <bits/stdc++.h>
using namespace std;
#define int long long
int dp[25][25];
int dx[8]={-1,-2,-2,-1,1,2,2,1},dy[8]={-2,-1,1,2,2,1,-1,-2};
signed main(){
int n,m,x,y;
cin>>n>>m>>x>>y;
dp[0][0]=1;//初始值
bool ok=1;
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
if(i==0&&j==0)continue;//不能是初始点
ok=1;
if(i==x&&j==y)ok=0;//这个点是不是马的位置
for(int k=0;k<8;k++){//这个点有没有被马控制
if(i==x+dx[k]&&j==y+dy[k]){ok=0;break;}
}
if(ok){//转移
if(i-1<0){//判断越界
dp[i][j]=dp[i][j-1];
}
else if(j-1<0){
dp[i][j]=dp[i-1][j];
}
else{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
}
}
cout<<dp[n][m]<<endl;
return 0;
}
标签:25,int,题解,P1002,马能,转移,dp
From: https://www.cnblogs.com/xdh2012/p/17966555