关于蒟蒻的我,刚刚接触DP....
那么就来做一道简单DP吧....
首先先看题:
题目描述
棋盘上AA点有一个过河卒,需要走到目标BB点。卒行走的规则:可以向下、或者向右。同时在棋盘上CC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,AA点(0, 0)(0,0)、BB点(n, m)(n,m)(nn, mm为不超过2020的整数),同样马的位置坐标是需要给出的。
现在要求你计算出卒从AA点能够到达BB点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入输出格式
输入格式:
一行四个数据,分别表示BB点坐标和马的坐标。
输出格式:
一个数据,表示所有的路径条数。
输入输出样例
输入样例#1:
6 6 3 3
输出样例#1:
6
说明
结果可能很大!
虽然简单,但AC过程还是那样艰巨...(好吧这道题因为简单有的人还在考虑它到达算不算DP...
废话少说,呈上AC代码,简单易懂...
此题一定要注意数据可能很大,要用long long类型!!!
1 #include//懒懒的我用了万能头文件 2 using namespace std; 3 typedef long long ll; //将long long 定义为ll(好吧还是因为我懒 4 const int maxn = 30; 5 6 ll ans[maxn][maxn]; //用来存储答案(路径个数) 7 int vis[maxn][maxn]; //用来将卒不能走的点打标记 8 int dir1[8] = { 1,1,2,2,-1,-1,-2,-2}; //将马的横坐标变化方式存入dir1数组中 9 int dir2[8] = { 2,-2,1,-1,2,-2,1,-1}; //将马的纵坐标变化方式存入dir2数组中 10 11 int main() 12 { 13 int n,m,cx,cy; //用cx、cy分别存储马坐标的横纵坐标14 cin>>n>>m>>cx>>cy; 15 memset(vis, 0, sizeof(vis)); //将打标记的vis数组进行初始化16 vis[cx][cy] = 1;//首先将马的坐标打标记,卒不能通过 17 for(int i = 0; i < 8; ++i){ 18 int a = cx + dir1[i]; //用a来存储马能够达到的横坐标19 int b = cy + dir2[i]; //用b来存储马能够达到的纵坐标20 if(a >= 0 && b >= 0 && a <= n && b <= n){ 21 vis[a][b] = 1; //首先判断a、b两坐标所表示的点是否合法(即是否在棋盘中),然后将这个点标记为1,即卒不能到达22 } 23 } 24 ans[0][0] = 1; //从起点到起点的方案数为0(废话 构造递推式25 for(int i = 0; i <= n; ++i){ 26 for(int j = 0; j <= m; ++j){ 27 if(i){ //若i为零,则不考虑上边的情况28 if(vis[i][j]) ans[i][j] = 0; //如果vis被标为1(即卒不能通过),则方案数为0 29 else ans[i][j] += ans[i-1][j]; //如果vis仍为0 (即卒能通过),则进行递推30 } 31 if(j){ //若j为零,则不考虑左边的情况32 if(vis[i][j]) ans[i][j] = 0; //如果vis被标为1(即卒不能通过),则方案数为033 else ans[i][j] += ans[i][j-1]; //如果vis仍为0 (即卒能通过),则进行递推34 } 35 } 36 } 37 cout< <