洛谷题目<过河卒>
题目描述
棋盘上 A 点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,A点 (0, 0)、B点 (n, m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 A 点能够到达 B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入格式
一行四个正整数,分别表示 B 点坐标和马的坐标。
输出格式
一个整数,表示所有的路径条数。
输入输出样例
输入
6 6 3 3
输出
6
说明/提示
对于 100 % 的数据,1<=n,m<=20,0<=马的坐标<=20.
分析一下
第一种想法,这道题刚入手的时候,想到的是通过查找,由于数据较小,可以将所有的点通过二维数组表示出来,能够通过的点就赋值为1,不能通过的点就赋值为0。但是仔细想过后,发现不能够解决问题,当面临着可以向下走,也可以向左走的时候,该如何选择?就算选择了其中一种路径,可是继续走下去后,假如到达目标点或者遇到了死胡同,不能继续往前走了,又该如何返回并尝试另一种路径呢?
以上问题让我当时否定了我的这种想法,也许以后能够有办法解决,但是目前这个问题我一点思路还都没有。
第二种想法,我想到由一个点在坐标轴中到达另一个点的路径有多少种的问题,我在高中曾经遇到过这种数学题,也就是排列组合C(n,m),这个想法给我提供了另一种思路,假如说从点(0,0)到达点(3,4)的话,路径一共有C(7,3)或C(7,4)种。也许能够通过这个办法解决这个问题。可以先计算出由点(0,0)到(n,m)的总路径数,然后减去那些经过了马的控制点的路径,这个计算可以通过由点(0,0)到马的控制点的路径数 乘以 该控制点到目标点的路径数,但是减去的过程中,还会减去经过两个马的控制点的路径数(那些重复的部分)。这样下来,计算量会非常的大,而且很容易就多减去了,这种方法可能在最后我抽丝剥茧后会得出来正确结果,但是这种复杂程度,太容易错误。
重点来啦
最后我在洛谷上看了大神的题解,了解到一种方法:假设到达点(i,j)的路径数为f[i][j]条,那么f[i][j]=f[i-1][j]+f[i][j-1]。这个是重点,那么就可以通过递推来计算出到达那个点的路径。
上代码:
#include<iostream>
using namespace std;
//20-7-8改 下面被注释掉的部分是昨天7-7写的,可惜写了半天,还是没写出来,于是今天去落谷上看题解了,有了一些思路,再来。
int main()
{
int n,m,x,y,i,j;
long long f[25][25]={0};
int g[25][25]={0};
cin>>n>>m>>x>>y;
//防止越界
if(x<=18 && y<=19)
g[x+2][y+1]=1;
if(x<=19 && y<=18)
g[x+1][y+2]=1;
if(x>=1 && y<=18)
g[x-1][y+2]=1;
if(x>=2 && y<=19)
g[x-2][y+1]=1;
if(x>=2 && y>=1)
g[x-2][y-1]=1;
if(x>=1 && y>=2)
g[x-1][y-2]=1;
if(x<=19 && y>=2)
g[x+1][y-2]=1;
if(x<=18 && y>=1)
g[x+2][y-1]=1;
g[x][y]=1 ;
//递推实现
for(i=0;i<=n;i++)
for(j=0;j<=m;j++)
if(!g[i][j])//不为马的控制点时
{
if(i==0 && j==0)
f[0][0]=1;//最初
else if(i==0 && j>0)
f[0][j]=f[0][j-1];
else if(i>0 && j==0)
f[i][0]=f[i-1][0];
else
f[i][j]=f[i-1][j]+f[i][j-1];
}
cout<<f[n][m]<<endl;
return 0;
}
//下面这部分是我第二种思路,可惜最后失败了。
//#include <iostream>
//using namespace std;
//int cou(int x,int y)
//{
// if(x<0 || y<0)
// {
// return(0);
// }
// int i,j,sum1=1,sum2=1,n,sum;
// n=x+y;
// for(i=n,j=1;j<=x;i--,j++)
// {
// sum1=i*sum1;
// }
// for(i=1;i<=x;i++)
// {
// sum2=i*sum2;
// }
// sum=sum1/sum2;
// return sum;
//}
//int main()
//{
// int a[28];
// int i,j,m,n,x,y,sum;
// cin>>n>>m>>x>>y;
// sum=cou(n,m);
// a[0]=cou(x+2,y+1)*cou(n-x-2,m-y-1);
// a[1]=cou(x+1,y+2)*cou(n-x-1,m-y-2);
// a[2]=cou(x-1,y+2)*cou(n-x+1,m-y-2);
// a[3]=cou(x-2,y+1)*cou(n-x+2,m-y-1);
// a[4]=cou(x-2,y-1)*cou(n-x+2,m-y+1);
// a[5]=cou(x-1,y-2)*cou(n-x+1,m-y+2);
// a[6]=cou(x+1,y-2)*cou(n-x-1,m-y+2);
// a[7]=cou(x+2,y-1)*cou(n-x-2,m-y+1);
// for(i=0;i<8;i++)
// {
// sum=sum-a[i];
// }
// a[0]=cou(x-1,y+2)*cou(n-x-1,m-y-2);
// a[1]=cou(x-2,y+1)*2*cou(n-x+1,m-y-2);
// a[2]=cou(x-2,y-1)*cou(1,3)*cou(n-x+1,m-y-2);
// a[3]=cou(x-1,y-2)*cou(n-x+1,m-y-2);
// a[4]=cou(x-2,y+1)*cou(3,1)*cou(n-x-1,m-y-2);
// a[5]=cou(x-2,y-1)*cou(3,3)*cou(n-x-1,m-y-2);
// a[6]=cou(x-1,y-2)*cou(2,4)*cou(n-x-1,m-y-2);
// a[7]=cou(x+1,y-2)*cou(n-x-1,m-y-2);
// a[8]=cou(x-2,y+1)*cou(n-x-2,m-y-1);
// a[9]=cou(x-2,y-1)*cou(4,2)*cou(n-x-2,m-y-1);
// a[10]=cou(x-1,y-2)*cou(3,3)*cou(n-x-2,m-y-1);
// a[11]=cou(x+1,y-2)*cou(1,3)*cou(n-x-2,m-y-1);
// a[12]=cou(x+2,y-1)*cou(n-x-2,m-y-1);
// a[13]=cou(x-2,y-1)*cou(n-x+2,m-y-1);
// a[14]=cou(x-2,y-1)*cou(n-x-2,m-y+1);
// a[15]=cou(x-1,y-2)*cou(n-x-1,m-y+2);
// a[16]=cou(x+1,y-2)*cou(n-x-2,m-y+1);
// a[17]=cou(x-2,y+1)*2*cou(n-x-1,m-y-2);
// a[18]=cou(x-2,y-1)*cou(1,2)*cou(n-x-1,m-y-2);
// a[19]=cou(x-1,y-2)*cou(n-x-1,m-y-2);
// a[20]=cou(x-2,y-1)*2*cou(n-x+1,m-y-2);
// a[21]=cou(x-1,y-2)*cou(n-x-1,m-y-2);
// a[22]=cou(x-2,y-1)*cou(n-x-2,m-y-1);
// a[23]=cou(x-1,y-2)*cou(n-x-2,m-y-1);
// a[24]=cou(x-1,y-2)*cou(3,1)*cou(n-x-2,m-y-1);
// a[25]=cou(x+1,y-2)*2*cou(n-x-2,m-y-1);
// a[26]=cou(x-2,y-1)*cou(n-x-2,m-y-1);
// a[27]=cou(x-1,y-2)*2*cou(n-x-2,m-y+1);
// for(i=0;i<28;i++)
// {
// sum=sum+a[1];
// }
// cout<<sum<<endl;
//}
第一次写,: ) 有点乱,以后尽量改一下。
再来个大神题解链接吧