题解 P1002 【过河卒】

· · 题解

标数法

这题让我不禁想起了小学奥数的标数法

A
B

只能往右或往下走,不能走水,请问从A到B有几种走法?

我们都会这样做:

1 1 1
1 2 3
1 0 3
1 1 4
1 2 6

所以共六种走法,这是因为只能往右或往下走,所以每一个格子的走法数,都是上面一个格子加上左边一个格子。

显然,我们已经找到了转移方程

map[i][j]=map[i-1][j]+map[i][j-1];

另外,所有不能经过的格子,我们都要标零

因为马走日,所以我们要将9个格子都标零:

!((i==x+2&&j==y+1)||(i==x+2&&j==y-1)||(i==x+1&&j==y+2)||(i==x+1&&j==y-2)||(i==x-1&&j==y+2)||(i==x-1&&j==y-2)||(i==x-2&&j==y+1)||(i==x-2&&j==y-1)||(i==x&&j==y))

(特别长对吧)这样我们就能判断是不是马的占领点

然后一行一行的标数:

for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(!((i==x+2&&j==y+1)||(i==x+2&&j==y-1)||(i==x+1&&j==y+2)||(i==x+1&&j==y-2)||(i==x-1&&j==y+2)||(i==x-1&&j==y-2)||(i==x-2&&j==y+1)||(i==x-2&&j==y-1)||(i==x&&j==y)))
                map[i][j]=map[i-1][j]+map[i][j-1];
最后就是这样: 1 1 1 1 1 1 1
1 2 0 1 0 1 2
1 0 0 1 1 0 2
1 1 1 0 1 1 3
1 0 1 1 2 0 3
1 1 0 1 0 0 3
1 2 2 3 3 3 6

非常容易 上完整代码(就不加注释了~ 。~)

#include<iostream>
#include<cstring>
using namespace std;

int x,y,m,n;
long long map[25][26];
int main(){
    cin>>n>>m>>x>>y;
    m++,n++,x++,y++;
    memset(map,0,sizeof(map)); 
    map[1][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(!((i==x+2&&j==y+1)||(i==x+2&&j==y-1)||(i==x+1&&j==y+2)||(i==x+1&&j==y-2)||(i==x-1&&j==y+2)||(i==x-1&&j==y-2)||(i==x-2&&j==y+1)||(i==x-2&&j==y-1)||(i==x&&j==y)))
                map[i][j]=map[i-1][j]+map[i][j-1];
//              cout<<'1'<<endl;
    cout<<map[n][m];
    return 233;
}
//((i != x+2&&j != y+1)&&(i != x+2&&j != y-1)&&(i != x+1&&j != y+2)&&(i != x+1&&j != y-2)&&(i != x-1&&j != y+2)&&(i != x-1&&j != y-2)&&(i != x-2&&j != y+1)&&(i != x-2&&j != y-1)&&(i != x&&j != y))