题目描述
棋盘上 �A 点有一个过河卒,需要走到目标 �B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 �C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,�A 点 (0,0)(0,0)、�B 点 (�,�)(n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 �A 点能够到达 �B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入格式
一行四个正整数,分别表示 �B 点坐标和马的坐标。
输出格式
一个整数,表示所有的路径条数。
输入输出样例
输入 #1复制
6 6 3 3
输出 #1复制
6
说明/提示
对于 100%100% 的数据,1≤�,�≤20 1≤n,m≤20,0≤0≤ 马的坐标 ≤20≤20。
对于该题可以说是01背包的形态转换,基本上也是以01背包的思想为主,稍微改动了一些但是换汤不换药。这种到达某个点的题目总是让人难以控制自己去想要使用搜索,但是貌似小小的值是可以的,但是20*20的一个map就有点大,导致有部分情况求解不出来,所以这边的最优解就是使用01背包的方法。
基本思路
首先,马可以产生对小兵的障碍(如果都在界内的话有八个,但是还有存在在界外的情况,注意判断),其次,小兵每一步只有两种选择,向下或者向右,关键点统计完了就是对于01背包的二维数组的建立,这一题明显需要一个book数组来记录是否可以走这一条路。
使用Map[i][j]二维数组来记录这一个点到来有多少种方法,很明显通过小兵只能向右或者向下表示在最边缘的部位,有且只有一种方法到(或者因为边缘有马的控制点这辈子小兵都到不了)需要判断,其他的位置到达方法就是左边的点的能到达方式数加上上面的点的能到达的方式数,建立二维数组,即可求出最后的Map[i][j]的值
基本代码如下
#include<stdio.h>
#define N 21
int main()
{
long long int Map[N][N]={0};
int book[N][N]={0};
int n,m,mx,my,tx,ty;
scanf("%d%d%d%d",&n,&m,&mx,&my);
int mmm[8][2]={{1,-2},{2,-1},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2}};
for(int i=0;i<8;i++)
{
tx=mx+mmm[i][0];
ty=my+mmm[i][1];
if(tx<0||ty<0||tx>20||ty>20)
{
continue;
}
else
{
book[tx][ty]=1;
}
}
book[mx][my]=1;
for(int i=0;i<21;i++)
{
for(int j=0;j<21;j++)
{
if(book[i][j]==0)
{
if(i==0&&j==0)
{
Map[i][j]=1;
}
else if(i==0)
{
Map[i][j]=Map[i][j-1];
}
else if(j==0)
{
Map[i][j]=Map[i-1][j];
}
else
{
Map[i][j]=Map[i-1][j]+Map[i][j-1];//背包中的基本公式
}
}
else
{
Map[i][j]=0;
}
}
}
printf("%lld\n",Map[n][m]);
getchar();
getchar();
return 0;
}
注:这题的Map必须开一个long long,没开有些值太大了导致题目ac不了