列表

详情


DP13. [NOIP2002 普及组] 过河卒

描述

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

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

注:马一次跳跃到达的点(x1,y1)和马原坐标(x,y)的关系是 


数据范围: ,马的坐标 

输入描述

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

输出描述

输出路径总数

示例1

输入:

6 6 3 3

输出:

6

示例2

输入:

5 4 2 3

输出:

3

示例3

输入:

2 5 3 5

输出:

1

原站题解

C 解法, 执行用时: 2ms, 内存消耗: 312KB, 提交时间: 2022-07-26

#include <stdio.h>

int fun(int x,int y,int n,int m);

int main(){
    int n = 0,m = 0,x = 0,y = 0;
    scanf("%d %d %d %d",&n,&m,&x,&y);
    long dp[n+1][m+1];
    for(int i = 0; i < n+1; i++){
        for(int j = 0; j < m+1; j++){
            if ((abs(i - x) + abs(j - y)) == 3 && i != x && j != y){
               dp[i][j] = -1; 
            }
            else
                dp[i][j] = 0;
        }
    }
    if (x >= 0 && x <= n && y >= 0 && y <= m)
        dp[x][y] = -1;
    int i = 0;
    int j = 0;
//     if(fun(x,y,n,m)) dp[x][y] = -1;
//     if(fun(x+2,y+1,n,m)) dp[x+2][y+1] = -1;
//     if(fun(x+1,y+2,n,m)) dp[x+1][y+2] = -1;
//     if(fun(x-1,y+2,n,m)) dp[x-1][y+2] = -1;
//     if(fun(x-2,y+1,n,m)) dp[x-2][y+1] = -1;
//     if(fun(x-2,y-1,n,m)) dp[x-2][y-1] = -1;
//     if(fun(x-1,y-2,n,m)) dp[x-1][y-2] = -1;
//     if(fun(x+1,y-2,n,m)) dp[x+1][y-2] = -1;
//     if(fun(x+2,y-1,n,m)) dp[x+2][y-1] = -1;
    for(i = 0; i < n+1; i++){
        if(dp[i][0] == -1)
            break;
        dp[i][0] = 1;
    }
    for(j = 0; j < m+1; j++){
        if(dp[0][j] == -1)
            break;
        dp[0][j] = 1;
    }
    for(i = 1; i < n+1; i++){
        for(j = 1; j < m+1; j++){
            if(dp[i][j] == -1 || (dp[i-1][j] == -1 && dp[i][j-1] == -1)){
                continue;
            }
            else if(dp[i-1][j] == -1 && dp[i][j-1] != -1){
                dp[i][j] = dp[i][j-1];
            }
            else if(dp[i-1][j] != -1 && dp[i][j-1] == -1){
                dp[i][j] = dp[i-1][j];
            }
            else{
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
    }
    printf("%ld",dp[i-1][j-1]);
    return 0;
}

int fun(int x,int y,int n,int m){
    if(x >= 0 && x <= n && y >= 0 && y <= m)
        return 1;
    else
        return 0;
}
int abs(int x){
    if (x >= 0)
        return x;
    else
        return -1 * x;
}

C++ 解法, 执行用时: 2ms, 内存消耗: 472KB, 提交时间: 2022-06-18

#include<iostream>
using namespace std;
#include<vector>
#include<cmath>

int main(){
    int n,m,x,y;
    cin>>n>>m>>x>>y;
    vector<vector<long long>> dp(n+1,vector<long long>(m+1));
    for(int i=0;i<=n;i++){
        if(abs(x-i)+abs(y-0)==3&&x!=i&&y!=0||x==i&&y==0)
            break;
        dp[i][0]=1;
    }
    for(int j=0;j<=m;j++){
        if(abs(x-0)+abs(y-j)==3&&x!=0&&y!=j||x==0&&y==j)
            break;
        dp[0][j]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(abs(x-i)+abs(y-j)==3&&x!=i&&y!=j||x==i&&y==j)
                continue;
            dp[i][j]=dp[i-1][j]+dp[i][j-1];
        }
    }
    cout<<dp[n][m]<<endl;
    return 0;
}

C 解法, 执行用时: 3ms, 内存消耗: 352KB, 提交时间: 2022-06-19

#include <stdio.h>

int check(int i, int j, int x, int y) {
    return (abs(i-x) + abs(j-y) == 3 && i != x && j != y) || (i == x && j == y);
}

int main() {
    int n, m, x, y;
    scanf("%d %d %d %d", &n, &m, &x, &y);
    
    int i = 0;
    long long **dp = (long long **)malloc(sizeof(long long *) * (n + 1));
    for (i = 0; i < n + 1; i++) {
        dp[i] = (long long *)malloc(sizeof(long long) * (m + 1));
    }
    dp[0][0] = 1;
    for (i = 1; i < n + 1; i++) {
        dp[i][0] = (check(i, 0, x, y) ? 0 : dp[i-1][0]);
    }
    for (int j = 1; j < m + 1; j++) {
        dp[0][j] = (check(0, j, x, y) ? 0 : dp[0][j-1]);
    }
    for (i = 1; i < n + 1; i++) {
        for (int j = 1; j < m + 1; j++) {
            dp[i][j] = (check(i, j, x, y) ? 0 : (dp[i-1][j] + dp[i][j-1]));
        }
    }
    
    printf("%lld", dp[n][m]);
    
    for (i = 0; i < n + 1; i++) {
        free(dp[i]);
    }
    free(dp);
    
    return 0;
}





C 解法, 执行用时: 3ms, 内存消耗: 360KB, 提交时间: 2022-07-01

#include <stdio.h>

int fun(int x,int y,int n,int m);

int main(){
    int n = 0,m = 0,x = 0,y = 0;
    scanf("%d %d %d %d",&n,&m,&x,&y);
    long dp[n+1][m+1];
    for(int i = 0; i < n+1; i++){
        for(int j = 0; j < m+1; j++){
            dp[i][j] = 0;
        }
    }
    int i = 0;
    int j = 0;
    if(fun(x,y,n,m)) dp[x][y] = -1;
    if(fun(x+2,y+1,n,m)) dp[x+2][y+1] = -1;
    if(fun(x+1,y+2,n,m)) dp[x+1][y+2] = -1;
    if(fun(x-1,y+2,n,m)) dp[x-1][y+2] = -1;
    if(fun(x-2,y+1,n,m)) dp[x-2][y+1] = -1;
    if(fun(x-2,y-1,n,m)) dp[x-2][y-1] = -1;
    if(fun(x-1,y-2,n,m)) dp[x-1][y-2] = -1;
    if(fun(x+1,y-2,n,m)) dp[x+1][y-2] = -1;
    if(fun(x+2,y-1,n,m)) dp[x+2][y-1] = -1;
    for(i = 0; i < n+1; i++){
        if(dp[i][0] == -1)
            break;
        dp[i][0] = 1;
    }
    for(j = 0; j < m+1; j++){
        if(dp[0][j] == -1)
            break;
        dp[0][j] = 1;
    }
    for(i = 1; i < n+1; i++){
        for(j = 1; j < m+1; j++){
            if(dp[i][j] == -1 || (dp[i-1][j] == -1 && dp[i][j-1] == -1)){
                continue;
            }
            else if(dp[i-1][j] == -1 && dp[i][j-1] != -1){
                dp[i][j] = dp[i][j-1];
            }
            else if(dp[i-1][j] != -1 && dp[i][j-1] == -1){
                dp[i][j] = dp[i-1][j];
            }
            else{
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
    }
    printf("%ld",dp[i-1][j-1]);
    return 0;
}

int fun(int x,int y,int n,int m){
    if(x >= 0 && x <= n && y >= 0 && y <= m)
        return 1;
    else
        return 0;
}

C++ 解法, 执行用时: 3ms, 内存消耗: 392KB, 提交时间: 2022-04-07

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include <cstring>
using namespace std;

int main()
{
	int n, m;
	cin >> n >> m;
	int x, y;
	cin >> x >> y;
	long long dp[n + 1][m + 1];
	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;
}

上一题