馬が川をせき止める

1793 ワード

Problem Description
碁盤のA点には川を渡る卒がいて、目標のB点まで歩く必要があります.歩行のルール:下へ、または右へ.同時に碁盤上のC点には相手の馬があり、その馬がいる点とジャンプして一歩で達する点を相手の馬の制御点と呼ぶ.そのため「馬が川を渡る卒」と呼ばれている.碁盤は座標で表され、A点(0,0)、B点(n,m)(n,mは15を超えない整数)であり、同じ馬の位置座標が与えられる必要がある.今、卒がA点からB点に到達できる経路の条数を計算し、馬の位置が固定されていると仮定し、卒走一歩馬が一歩歩くわけではない.
Input
1行に4つのデータをスペースで区切って、B点の座標と馬の座標をそれぞれ表します.
Output
すべてのパス・バー数を表すデータ.
Sample Input
6 6 3 3

Sample Output
6

分析:
実は、川を渡ってある点に到達する経路の数は、その隣接する上点と左点に到達する経路の数の和に等しいので、逐行(または列ごとに)押す方法で起点から終点までの経路の数を求めることができる.
2次元配列f[i][j]=点(i,j)までの経路数を2次元配列f[i][j]=1で馬の制御点であるか否かをg[i][j]=1で示すと仮定する.
f[i][j]=0 g[i][j]=1のとき;
f[i][0]=f[i-1][0]i>0;g[i][j]=0の場合;
f[i][j]=f[0][j-1]j>0;g[i][j]=0の場合;
f[i][j]=f[i-1][j]+f[i][j-1]当i>0;g[i][j]=0の場合;
そのうちf[0][0]=1;
コードは次のとおりです.
#include 
#include 
int main()
{
    int dy[9]={0,-2,-1,1,2,2,1,-1,-2};
    int dx[9]={0,1,2,2,1,-1,-2,-2,-1};
    int n,m,x,y,i,j;
    long long int f[20][20]={0};
    int g[20][20]={0};
    scanf("%d%d%d%d",&n,&m,&x,&y);
    g[x][y]=1;
    for(i=1;i<=8;i++)
    {
        if((x+dx[i]>=0)&&(x+dx[i]<=n)&&(y+dy[i]>=0)&&(y+dy[i]<=m))
            g[x+dx[i]][y+dy[i]]=1;
    }
    for(i=1;i<=n;i++)
    {
        if(g[i][0]!=1)f[i][0]=1;
        else {for(;i<=n;i++)f[i][0]=0;}
    }
    for(i=1;i<=m;i++)
    {
        if(g[0][i]!=1)f[0][i]=1;
        else {for(;i<=m;i++)f[0][i]=0;}
    }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            if(g[i][j]!=1)f[i][j]=f[i-1][j]+f[i][j-1];
            else f[i][j]=0;
        }
    }
    printf("%d",f[n][m]);

    return 0;
}