P1002题解

· · 题解

思路

设 dp_{i,j} 表示第 i 行 j 列卒走到这里有多少种方式。

卒是可以向右和下走,所以到这个点只能从左或上来,不难得出转移公式:dp_{i,j} = dp_{i-1,j}+dp_{i,j-1}。

如果马在这个点上或者说马能到这个点上,那么卒不能到这个点,也就是卒到这个点的方式为 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;
}