洛谷题解 P1002 【过河卒】

Author Avatar
Sophon 4月 12, 2019
| keyboard本文共:545字 | query_builder阅读时间≈2分 |
  • 在其它设备中阅读本文章

题目描述

棋盘上$A$点有一个过河卒,需要走到目标$B$点。卒行走的规则:可以向下、或者向右。同时在棋盘上$C$点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。

棋盘用坐标表示,$A$点$(0, 0)$、$B$点$(n, m)$($n$, $m$为不超过$20$的整数),同样马的位置坐标是需要给出的。

现在要求你计算出卒从$A$点能够到达$B$点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

输入输出格式

输入格式:

一行四个数据,分别表示$B$点坐标和马的坐标。

输出格式:

一个数据,表示所有的路径条数。

输入输出样例

输入样例#1:

6 6 3 3

输出样例#1:

6

说明

结果可能很大!


看到题目二话不说用了搜索,直到在提交前看了一下算法标签,又看了一下数据范围。。。

状态转移方程的推导并不复杂,每次判断卒是否能走到这个格子,不可以则为0(显而易见),可以则为下方与左方的值之和。

上代码,这道题算是一道DP入门题吧。

#include<stdio.h>

const int MAXN = 20 + 5;
const int attack[9][2] = {{0, 0}, {1, 2}, {2, 1}, {-1, 2}, {2, -1}, {1, -2}, {-2, 1}, {-1, -2}, {-2, -1}};
long long dist[MAXN][MAXN];
int map[MAXN][MAXN];
int n, m, x, y;

void init(void) {
    for(int i = 0; i < 9; i++) {
        if(x + attack[i][0] <= n && x + attack[i][0] >= 0) {
            if(y + attack[i][1] <= m && y + attack[i][1] >= 0) {
                map[x + attack[i][0]][y + attack[i][1]] = true;
            }
        }
    }
}

int main() {
    scanf("%d%d%d%d", &n, &m, &x, &y);

    init();

    int k = 1;
    for(int i = 0; i <= n; i++) {
        dist[i][0] = map[i][0] ? k = 0 : k;
    }
    k = 1;
    for(int i = 0; i <= m; i++) {
        dist[0][i] = map[0][i] ? k = 0 : k;
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            dist[i][j] = map[i][j] ? 0 : dist[i - 1][j] + dist[i][j - 1];
        }
    }

    printf("%lld\n", dist[n][m]);

    return 0;
}

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 许可协议。转载请注明出处!
本文链接:https://keepthethink.github.io/archives/2197869946/