Forever Young

洛谷 P1002 过河卒

洛谷 P1002 过河卒

思路

菜鸡小学生\(loceaner\)现在才知道过河卒怎么做……

首先我们把马的控制点全部标记一下(顺便判断一下边界,后面就不用判了)

然后用\(DP\)来做,需要注意的是如果\(f[0][0]\)也是马的控制点的话,就没法到达\(B\)点了,所以\((0,0)\)不是控制点才可以到达,且到达此点的方式只有一种,在代码中便是这一句if(!f[0][0]) dp[0][0] = 1;

之后便是\(DP\)过程了,循环过程中,如果当前点是马的控制点,则直接跳过,如果不是,只要\(i\)大于\(0\),便可以由\(dp[i-1][j]\)转化过来,只要\(j\)大于\(0\),就可以从\(dp[i][j - 1]\)转化过来,总体转移方程为

\[\begin{equation} dp[i][j] = dp[i][j] + \begin{cases} dp[i - 1][j] (i > 0)\\ dp[i][j-1](j >0)\\ \end{cases} \end{equation} \]

最后的答案显然在\(dp[bx][by]\)

代码

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

inline int read() {
	char c = getchar();
	int x = 0, f = 1;
	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
	return x * f;
}

int mx, my, bx, by;
long long dp[21][21];
bool f[21][21];

void pre(int i, int j) {
	if(i >= 0 && i <= bx && j >= 0 && j <= by)
		f[i][j] = true;
	return;
}

int main() {
	bx = read(), by = read(), mx = read(), my  = read();
	pre(mx, my);
	pre(mx - 2, my + 1);
	pre(mx - 2, my - 1);
	pre(mx - 1, my + 2);
	pre(mx - 1, my - 2);
	pre(mx + 1, my + 2);
	pre(mx + 1, my - 2);
	pre(mx + 2, my - 1);
	pre(mx + 2, my + 1);
	if(!f[0][0])dp[0][0] = 1;
	for(int i = 0; i <= bx; i++) {
		for(int j = 0; j <= by; j++) {
			if(f[i][j]) continue;
			if(i > 0) dp[i][j] += dp[i - 1][j];
			if(j > 0) dp[i][j] += dp[i][j - 1];
		}
	}
	cout << dp[bx][by] << '\n';
	return 0;
}
posted @ 2019-09-02 19:20  Loceaner  阅读(235)  评论(0编辑  收藏  举报