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("%d\n",a[i][j]);
if(flag[i-1][j-1]==-1)a[i][j]=0;
}
}
cout<<a[n+1][m+1]<<endl;
return 0;
}