zoukankan      html  css  js  c++  java
  • 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)。现在要求你计算出卒从 A 点能够到达 B 点的路径的条数。

    1<=n,m<=15

    输入描述 Input Description

     键盘输入
       B点的坐标(n,m)以及对方马的坐标(X,Y){不用判错}

    输出描述 Output Description

      屏幕输出
        一个整数(路径的条数)。

    样例输入 Sample Input

     6 6 3 2

    样例输出 Sample Output

    17

    题目分析:

    要到达棋盘上的一个点,只能从左边过来(我们称之为左点)或是从上面过来(我们称之为上点),所以根据加法原理,到达某一点的路径数目,就等于到达其相邻的上点和左点的路径数目之和,因此我们可以使用逐列(或逐行)递推的方法来求出从起点到终点的路径数目。障碍点(马的控制点)也完全适用,只要将到达该点的路径数目设置为0即可。

    用F[i][j]表示到达点(i,j)的路径数目,g[i][j]表示点(i, j)有无障碍,g[i][j]=0表示无障碍,g[i][j]=1表示有障碍。
    则,递推关系式如下: F[i][j] = F[i-1][j] + F[i][j-1] //i>0且j>0且g[i][j]= 0
    递推边界有4个:
        F[i][j] = 0 //g[i][j] = 1
        F[i][0] = F[i-1][0] //i > 0且g[i][0] = 0
        F[0][j] = F[0][j-1] //j > 0且g[0][j] = 0
        F[0][0] = 1
    考虑到最大情况下:n=20,m=20,路径条数可能会超过231-1,所以要用高精度。

     1 #include <stdio.h>
     2 int main(int argc, char *argv[])
     3 {
     4     int F[21][21]={0},G[21][21]={0};
     5     int i,j;
     6     int n,m;//终点坐标
     7     int a,b;//马的坐标
     8     
     9     scanf("%d%d",&n,&m);//输入终点坐标 
    10     scanf("%d%d",&a,&b);//输入马的坐标    
    11     
    12     G[a][b]=1;
    13     if(a-2>=0&&b-1>=0)    {G[a-2][b-1]=1;}
    14     if(a-2>=0&&b+1<=m)    {G[a-2][b+1]=1;}
    15     if(a+2<=n&&b-1>=0)    {G[a+2][b-1]=1;}
    16     if(a+2<=n&&b+1<=m)    {G[a+2][b+1]=1;}
    17     
    18     if(a-1>=0&&b-2>=0)    {G[a-1][b-2]=1;}
    19     if(a-1>=0&&b+2<=m)    {G[a-1][b+2]=1;}
    20     if(a+1<=n&&b-2>=0)    {G[a+1][b-2]=1;}
    21     if(a+1<=n&&b+2<=m)    {G[a+1][b+2]=1;}
    22     
    23     for(i=0;i<=n;i++)//初始化第一行和第一列,均为1种走法。 
    24     {
    25         if(G[i][0]==0){F[i][0]=1;}
    26         else break;
    27     }
    28     for(i=0;i<=m;i++)
    29     {
    30         if(G[0][i]==0) {F[0][i]=1;}
    31         else break;
    32     }
    33     for(i=1;i<=m;i++)
    34     {
    35         for(j=1;j<=n;j++)
    36         {
    37             if(G[j][i]!=1)
    38             {
    39                 F[j][i]=F[j-1][i]+F[j][i-1];
    40             }
    41         }
    42     }
    43     printf("%d",F[n][m]);
    44     
    45     return 0;
    46 }

    另一段比较优秀的代码:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 int detX[8]={2,1,-1,-2,-2,-1,+1,+2};
     4 int detY[8]={1,2,+2,+1,-1,-2,-2,-1};
     5 int main()
     6 {
     7     int n,m,x,y,i,j;
     8     long long F[25][25]={0};
     9     int xx,yy;
    10     scanf("%d%d%d%d",&n,&m,&x,&y);
    11 
    12     F[x][y]=-1;
    13     for(i=0;i<8;i++)
    14     {
    15         xx=x+detX[i];  yy=y+detY[i];
    16         if(xx>=0&&xx<=n&&yy>=0&&yy<=m) F[xx][yy]=-1;
    17     }
    18 
    19     F[0][0]=1;
    20     for(i=1;i<=n;i++)//初始化第0列
    21     {
    22         if(F[i][0]!=-1) F[i][0]=F[i-1][0];
    23         else F[i][0]=0;
    24     }
    25     for(j=1;j<=m;j++)//初始化第0行
    26     {
    27         if(F[0][j]!=-1) F[0][j]=F[0][j-1];
    28         else F[0][j]=0;
    29     }
    30 
    31     for(i=1;i<=n;i++)
    32     {
    33         for(j=1;j<=m;j++)
    34         {
    35             if(F[i][j]!=-1) F[i][j]=F[i][j-1]+F[i-1][j];
    36             else F[i][j]=0;
    37         }
    38     }
    39     printf("%lld
    ",F[n][m]);
    40     return 0;
    41 }
  • 相关阅读:
    [LeetCode 1029] Two City Scheduling
    POJ 2342 Anniversary party (树形DP入门)
    Nowcoder 106 C.Professional Manager(统计并查集的个数)
    2018 GDCPC 省赛总结
    CF 977 F. Consecutive Subsequence
    Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
    Poj 2337 Catenyms(有向图DFS求欧拉通路)
    POJ 1236 Network of Schools (强连通分量缩点求度数)
    POJ 1144 Network (求割点)
    POJ 3310 Caterpillar(图的度的判定)
  • 原文地址:https://www.cnblogs.com/huashanqingzhu/p/10324414.html
Copyright © 2011-2022 走看看