P1002 [NOIP2002 普及组] 过河卒
最近在洛谷刷题,决定用博客把自己的解题思路以及踩过的坑整理总结一下~
先来看看题目吧~
棋盘上 AA 点有一个过河卒,需要走到目标 BB 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 CC 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,AA 点 (0, 0)(0,0)、BB 点 (n, m)(n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 AA 点能够到达 BB 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入格式
一行四个正整数,分别表示 BB 点坐标和马的坐标。
输出格式
一个整数,表示所有的路径条数。
思路
刚拿到题的时候,有点不知道怎么做,只觉得要用动态规划,但是没有想好方程是怎么样的。
错得离谱的思路就不说了,说说还不错的思路。
定义一个数组用来存到该点的路径条数,路径条数怎么得到呢?
往下看
因为只能向下或向右去走,所以到一个点只有通过它左边的路或上边的路
那么来了!!!
到某点的路径条数=到它左边点的条数+到它上面点的条数(前提是这两点都可到)。
这时候我们想一想就可以得到动态规划方程
了
不过我这里倒是犯了一个错误,我想当然的把到边线上的点的路径条数默认成1了,虽然一般情况适用,可是当马的控制范围包含了某个边线上的点时,是WA了!
真正到边线上的点的路径条数应该是他的上一个点的条数(上边界就是它左边的点,左边姐就是它上边的点)
if(i==0&&j>0)//上边界
{
a[i][j]=a[i][j-1];
}
else if(j==0&&i>0)//左边界
{
a[i][j]=a[i-1][j];
}
那么还有一个特殊点,就是原点(起点),到它的路径条数是多少呢?
很明显,就是1了
if(i==0&&j==0)//原点
a[i][j]=1;
剩下的点就是普通点了,到它们的路径条数当然就是到它左边点的条数+到它上面点的条数
else
{
a[i][j]=a[i-1][j]+a[i][j-1];
}
要注意!!我们讨论的这三类点都是在它可到达的情况下讨论的,也就是说不受马控制的点,那么怎么实现呢?
当然在外面加一层if判断就好了!
好了,到这里,方程就基本出来了,剩下的就看代码吧,呼呼~
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m,p,q;//(n,m)终点 (p,q)马点
long long a[30][30];//路径条数,之前这里用了int,总有两个测试数据不过
//改成longlong就好了
int map[30][30];//能不能走,马控制的点设为1,代表不能走
cin>>n>>m>>p>>q;
//马的控制区域,1代表此路不通
map[p][q]=1;
map[p-2][q-1]=1;
map[p-2][q+1]=1;
map[p+2][q+1]=1;
map[p+2][q-1]=1;
map[p-1][q-2]=1;
map[p-1][q+2]=1;
map[p+1][q+2]=1;
map[p+1][q-2]=1;
/* 嘤嘤嘤 这里就是错误代码了,异想天开的我,以为边线上的点一定可以到。。。
for(int i=1;i<=n;i++)
{
a[i][0]=1;
}
for(int i=1;i<=m;i++)
{
a[0][i]=1;
}*/
//动态规划求到各点的路数
for(int i=0;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
if(map[i][j])
continue;
else //不受马控制的点
{
if(i==0&&j==0)
a[i][j]=1;
else if(i==0&&j>0)
{
a[i][j]=a[i][j-1];
}
else if(j==0&&i>0)
{
a[i][j]=a[i-1][j];
}
else
{
a[i][j]=a[i-1][j]+a[i][j-1];
}
}
}
}
cout<<a[n][m]<<endl;
return 0;
}
over,这道题就结束了~~第一次写博客,如果有帮到大家,非常荣幸,写得不好,也请见谅,啦啦