过河卒

时间:2022-07-25
本文章向大家介绍过河卒,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

P1002 过河卒 题目描述 棋盘上AAA点有一个过河卒,需要走到目标BBB点。卒行走的规则:可以向下、或者向右。同时在棋盘上CCC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。 棋盘用坐标表示,AAA点(0,0)(0, 0)(0,0)、BBB点(n,m)(n, m)(n,m)(nnn, mmm为不超过202020的整数),同样马的位置坐标是需要给出的。 现在要求你计算出卒从AAA点能够到达BBB点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。 输入输出格式 输入格式:

一行四个数据,分别表示BBB点坐标和马的坐标。 输出格式:

一个数据,表示所有的路径条数。 样例1: 6 6 3 3 输出1: 6 说明: 结果可能很大! 思路:数据范围可以longlong水过…,unsigned longlong当然也行… 一开始用dfs爆搜 标记马所能走到的位置,记为-1表示不能走,从起点深搜,向右向下超出边界或遇到马能到的点返回 只拿40分 40分代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll ans;
int n,m,c,d;
int a[500][500],dx[2]={0,1},dy[2]={1,0},dhorsex[10]={0,-1,-1,1,1,-2,-2,2,2},dhorsey[10]={0,-2,2,-2,2,1,-1,1,-1};
void dfs(int x,int y)
{
    if(x==n&&y==m)
    {
        ans++;
        return ;
    }
    if(x<0||y<0||a[x][y]==-1||x>n||y>m)return;
    else
    {
        for(int i=0;i<2;i++)
        {
            dfs(x+dx[i],y+dy[i]);
        }
    }
}
int main()
{
scanf("%d%d%d%d",&n,&m,&c,&d);
for(int i=0;i<=8;i++)
{
    if((c+dhorsex[i])>=0&&(d+dhorsey[i])>=0)
    {
        a[c+dhorsex[i]][d+dhorsey[i]]=-1;
    }
}
dfs(0,0);
cout<<ans<<endl;
    return 0;
}

最后看题解是记忆化递推,原来是入门dp题… 状态转移方程很好想:f[i][k]=f[i-1][k]+f[i][k-1](f[i][j]表示从(0,0)移动到(i,k)点一共可能的路径数目) 因为它只能来自上一状态(两种选择,往下走,往右走) ACcode

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll ans;
int n,m,c,d;
ll a[500][500];
int dhorsex[10]={0,-1,-1,1,1,-2,-2,2,2},dhorsey[10]={0,-2,2,-2,2,1,-1,1,-1},flag[500][500];
int main()
{
scanf("%d%d%d%d",&n,&m,&c,&d);
for(int i=0;i<=8;i++)
{
    if((c+dhorsex[i])>=0&&(d+dhorsey[i])>=0)
    {
        flag[c+dhorsex[i]][d+dhorsey[i]]=-1;
    }
}
a[1][0]=1;
for(int i=1;i<=n+1;i++)
{
    for(int j=1;j<=m+1;j++)
    {
        a[i][j]=a[i-1][j]+a[i][j-1];
      //  printf("%dn",a[i][j]);
            if(flag[i-1][j-1]==-1)a[i][j]=0;
    }
}
cout<<a[n+1][m+1]<<endl;
    return 0;
}