P1002 过河卒

题目描述

棋盘上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

说明/提示

结果可能很大!

 

思路:由题意卒可以向下或向右走,可以很明确的分辨出两个状态。由此可以判断出可以使用DP来解决问题。

我们可以设f[i][j]表示从(0,0)到达(i,j)的路径的数目。f[i][j]的属性为数字的和。

我们将f[i][j]看作是一个集合,那么它可以划分成那些不同的集合呢,明显可以划分成f[i-1][j]和f[i][j-1]。

因此得出状态转移方程 f[i][j] = f[i-1][j] + f[i][j-1] ;

由于涉及到 i-1 ,j-1等,要把整个矩阵右移,所以下标加1。

并且由于我们遍历是要从(1,1)开始,如果用上述方程那么f[1][1]将会由1变为0。

所以我们用 方程

f[i][j]=max(f[i-1][j]+f[i][j-1],f[i][j]);来表示。这两个方程本质没区别,只针对(1,1)这个点,其余的点f[i-1][j]+f[i][j-1]一定比f[i][j]大

#include <iostream>

using namespace std;
long long f[50][50];
bool v[50][50];
int main()
{
    int x1,y1,x2,y2;
    cin >> x1 >> y1 >> x2 >> y2;
    x1++,y1++,x2++,y2++;
    f[1][1]=1;
    v[x2][y2]=1;
    if(x2-2>=1&&x2-2<=50&&y2-1>=1&&y2-1<=50)
        v[x2-2][y2-1]=1;
    if(x2-2>=1&&x2-2<=50&&y2+1>=1&&y2+1<=50)
        v[x2-2][y2+1]=1;
    if(x2-1>=1&&x2-1<=50&&y2-2>=1&&y2-2<=50)
        v[x2-1][y2-2]=1;
    if(x2-1>=1&&x2-1<=50&&y2+2>=1&&y2+2<=50)
        v[x2-1][y2+2]=1;
    if(x2+2>=1&&x2+2<=50&&y2-1>=1&&y2-1<=50)
        v[x2+2][y2-1]=1;
    if(x2+2>=1&&x2+2<=50&&y2+1>=1&&y2+1<=50)
        v[x2+2][y2+1]=1;
    if(x2+1>=1&&x2+1<=50&&y2-2>=1&&y2-2<=50)
        v[x2+1][y2-2]=1;
    if(x2+1>=1&&x2+1<=50&&y2+2>=1&&y2+2<=50)
        v[x2+1][y2+2]=1;
    for(int i=1;i<=x1;i++)
    {
        for(int j=1;j<=y1;j++)
        {
            if(!v[i][j])
            {
                f[i][j]=max(f[i-1][j]+f[i][j-1],f[i][j]);
            }
        }
    }
    cout << f[x1][y1] << endl;
    return 0;
}

 

posted @ 2019-10-08 17:41  晴天要下雨  阅读(164)  评论(0编辑  收藏  举报