过河卒(Noip2002)

【题目描述】

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。

【输入】

给出n、m和C点的坐标。

【输出】

从A点能够到达B点的路径的条数。

【输入样例】

8 6 0 4

【输出样例】

1617

例题不怎么详的解:

过河卒,中国象棋用语,过了河的卒可以向前、向左、向右移动,但是单单不能后退的,所以被广泛用来形容‘没有退路’。

也指的一种只能前进不能后退的破釜沉舟的勇气,或者是指做事小心谨慎步步为营的一种人生态度。

分析:本题中,卒只能向下和右移动,而不能往回走或往左走。可以很快看出,本题可以用搜索来做。但是根据书上来说,好像无法承受较大的数据规模。

书上给出的解法是递推这种抽象的解法,简直就像凑数一样。

递推的方法,我们可以用一个数组储存到某一点的路径总数,另一个数组(bool型)储存整张棋盘,来代表某个位置马是否能够到达。

假设用F[I,J]到达点(I,J)的路径数目用G[I,J]表示点(I,J)是否为对方马的控制点,G[I,J]=0表示不是对放马的控制点,G[I,J]=1表示是对方马的控制点。

那么有隐含条件:

F[I,J]=0{G[I,J]=1}

根据题目,可以看出卒要从左上到右下,那么只能以向下走和向右走的方法到达终点。换句话说,以逆推的思想,棋盘上的每一个点只能从这个点的左边或者上边到达,由此判断,如果在棋盘上面和左边的边缘上有马可以达到的位置,那么从这个点往后的剩下的整行或整列,卒都不能到达。

而且,从题目来看,这个卒的行走路径还具有很强的不可逆性,无法回头,很容易注意到,棋子每向右走一步,那么它上一步所在的位置的整列(colum)都将无法到达,得出递推关系式:

F[0,J]=F[0,J-1]{J>0,G[0,J]=0}

同理,棋子每向下走一步,那么踏上一步所在位置的整行(row)都将无法到达,则有递推关系式:

F[I,0]=F[I-1,0]{I>0,G[I,0]=0}

这两个关系式都可以看作是用来排除不可能条件的,对真正得出答案没用,缺少了一个核心递推式。

要让程序进行下去,最关键的关系式:

F[I,J]=F[I-1,J]+F[I,J-1]{I>0,J>0,G[I,J]=0}

这里很容易看明白,[i-1][j-1]代表的就是目前点[i,j]左边的点和上面的点总共的可到达路径条数,很明显,其总和就是该点的有效路径。

从一开始的很容易看出来的递推边界开始递推:

F[0,0]=1

即可得出答案。(哎,第一篇写的就这么麻烦,不过挺清楚的。)

样例代码如下:

#include<iostream>
#include<cstring>
using namespace std;
long long a[30][30];
int vis[30][30];
int next[][2]={{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}};
int main()
{
    int n,m;
    int x,y;
    int nx,ny;
    int i,j;

    memset(vis,0,sizeof(vis));
    cin>>n>>m>>x>>y;

    a[0][0]=0;//处理A=B的情况
    vis[x][y]=1;//设置马管辖的位置
    a[x][y]=0;
    for(i=0;i<8;i++)
    {
        nx=x+next[i][0];
        ny=y+next[i][1];
        if(0<=nx&&nx<=n&&0<=ny&&ny<=m)
        {
            vis[nx][ny]=1;
            a[nx][ny]=0;
        }
    }
    for(i=0;i<=n;i++)
    {
        if(vis[i][0]==1)
            while(i<=n)
            	{
                	i++;
                	a[i][0]=0;
            	}
        else
            a[i][0]=1;
    }
    for(j=0;j<=m;j++)
    {
        if(vis[0][j]==1)
            while(j<=m)
            {
                j++;
                a[0][j]=0;
            }
        else
            a[0][j]=1;
    }
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            if(vis[i][j]==0)
                a[i][j]=a[i][j-1]+a[i-1][j];
    cout<<a[n][m]<<endl;
    return 0;
}

2019-01-28 11:51:23

转载请联系作者

原文地址:https://www.cnblogs.com/DarkValkyrie/p/10329614.html

时间: 2024-07-30 20:08:25

过河卒(Noip2002)的相关文章

【例3.6】过河卒(Noip2002)

[题目描述] 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,--,P8,卒不能通过对方马的控制点.棋盘用坐标表示,A点(0,0).B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B.现在要求你计算出卒从A点能够到达B点的路径的条数. [输入] 给出n.m和C点的坐标. [输出] 从A点能够到达B点的路

1314:【例3.6】过河卒(Noip2002)

传送门: [题目描述] 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点.棋盘用坐标表示,A点(0,0).B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B.现在要求你计算出卒从A点能够到达B点的路径的条数. [输入] 给出n.m和C点的坐标. [输出] 从A点能够到

【水】noip2002普及 过河卒

这题似乎是当年的马拦过河卒,好久的回忆啊... 过河卒 来源 NOIP2002普及组 题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例 如上图 C 点上的马可以控制 9 个点(图中的P1,P2 … P8 和 C).卒不能通过对方马的控制点. 棋盘用坐标表示,A 点(0,0).B 点(n,m)(n,m 为不超过 25 的整数,并由键盘输入),同样马的

2002普及组第四题过河卒

题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如上图 C 点上的马可以控制 9 个点(图中的P1,P2 - P8 和 C).卒不能通过对方马的控制点. 棋盘用坐标表示,A 点(0,0).B 点(n,m)(n,m 为不超过 20 的整数,并由键盘输入),同样马的位置坐标是需要给出的(约定: C<>A,同时C<>B).现在要求你计算出卒

洛谷P1002 过河卒

看到就顺便做了 NOIP2002普及组.那个年代还没有int64,不得不用高精算,然而现在一个long long就解决了.感受到了时代的进步呢. 题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. 棋盘用坐标表示,A点(0, 0).B点(n, m)(n, m为不超过20的整数),同样马的位置坐标是需要给出的. 现在要求你计算出卒从A点能够到达B点的路

马拦过河卒心得体会

题目棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为"马拦过河卒". 棋盘用坐标表示,A点(0, 0).B点(n, m)(n, m为不超过15的整数),同样马的位置坐标是需要给出的.现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步. 输入一行四个数据,分别表示B点坐标和马的坐标.(保证所有的数据有解) 输出一个数据

codevs 1010 过河卒

题目描述 Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如上图 C 点上的马可以控制 9 个点(图中的P1,P2 - P8 和 C).卒不能通过对方马的控制点. 棋盘用坐标表示,A 点(0,0).B 点(n,m)(n,m 为不超过 20 的整数,并由键盘输入),同样马的位置坐标是需要给出的(约定: C不等于A,同时C不等于B).现在

AOJ 763.过河卒

过河卒 Time Limit: 1000 ms   Case Time Limit: 1000 ms   Memory Limit: 64 MBTotal Submission: 23   Submission Accepted: 5 Description 在一个n*m的矩阵上,A点有一个过河卒,需要走到目标B点.卒行走的规则:只能向下或者向右.每一步能水平或者垂直移动一个点(纵横线的交叉点)的距离.计算从A 点能够到达B点的路径的条数.设行.列数为m和n, 2<=m,n<=20 Input

过河卒

过河卒 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 941  Solved: 206 Description 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图中的C点和P1,……,P8,卒不能通过对方马的控制点.棋盘用坐标表示,A点(0,0).B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的