线性dp:DP13 [NOIP2002 普及组] 过河卒

描述:

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

棋盘用坐标表示,A 点 (0, 0)、B点(n,m),同样马的位置坐标是需要给出的。
现在要求你计算出卒从 A点能够到达 B点的路径的条数,假设马的位置(x,y)是固定不动的,并不是卒走一步马走一步。

输入描述:

仅一行,输入 n,m,x,y 四个正整数。分别表示B点坐标和马的坐标

输出描述:

输出路径总数

#include
#include
#include
#include
#include //memset头文件
using namespace std;

int main()
{
	int n, m;
	cin >> n >> m;
	int x, y;
	cin >> x >> y;
	
	//vector的类型:vector vi_1;vector vi_2;vector vi_3;
	/*
	long long **dp = new long long* [n + 1];
	for (int i = 0; i <= n; ++i)
	{
		dp[i] = new long long[m + 1];
		for (int j = 0; j <= m; ++j)
		{
			dp[i][j] = -1;
		}
	}
	*/
	long long dp[n + 1][m + 1];//这是C语言写法,在vs中报错,但笔试可以用
	memset(dp, -1, sizeof(dp));//初始化为-1,这里注意下标从0开始,所以是(n+1,m+1)
	dp[0][0] = 1;
	if (x <= n && y <= m) {
		dp[x][y] = 0;///将马所在点设为0
	}
	
	for (int i = 0; i <= n; ++i)
	{
		for (int j = 0; j <= m; ++j)
		{
			if (abs(i - x) + abs(j - y) == 3 && (i != x) && (j != y))
			{
				dp[i][j] = 0;//将拦马点设为0
			}
		}
	}
	for (int i = 1; i <= n; ++i)
	{
		if (dp[i][0]!=0)
			dp[i][0] = dp[i-1][0];//初始化第一列
	}
	for (int j = 1; j <= m; ++j)
	{
		if (dp[0][j]!=0)
			dp[0][j] = dp[0][j-1];//初始化第一行
	}

	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= m; ++j)
		{
			if (dp[i][j]!=0)
				dp[i][j] = dp[i - 1][j] + dp[i][j - 1];//dp[i]不为0的点才有路径
		}
	}
	cout << dp[n][m];
	return 0;
}

你可能感兴趣的:(动态规划算法类专题,动态规划,C++)