DP——Simple Chess

题目描述

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

棋盘用坐标表示,AA 点 (0, 0)(0,0)、BB 点 (n, m)(n,m),同样马的位置坐标是需要给出的。

 

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

输入格式

一行四个正整数,分别表示 BB 点坐标和马的坐标。

输出格式

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

输入输出样例

 输入 #1
6 6 3 3
输出 #1
6


思路
第一,这不是一个搜索的题目,搜索的话如果棋盘增大的话就会超时
另外,对于DP问题来说,最关键的就是递推公式,即当前状态的解怎么由前面几个状态的解推导得到。


具体做法
定义一个dp[i][j]的数组来存储i行j列位置的不同路径的数目,定义一个flag[i][j]的数组标记位置i行j列是否不可达
在这道题目里,卒只能向下或者向右移动,所以当前位置的解等于邻接上面位置的解加上邻接左边位置的解,也就是dp[i][j]=dp[i-1][j]+dp[i][j-1]


首先把马能走到的位置提前进行标记,并让这个位置的解(dp[i][j])为0,因为没有路径能够到达。

其次遍历0行和0列,令解为1直到遇到之前标记的元素(也就是马能走到的)。因为第0行和第0列的每个位置只有一种路径,就是从(0,0)一直向右或者一直向下。

最后从1行1列开始遍历,如果当前元素未被标记,则dp[i][j]=dp[i-1][j]+dp[i][j-1]。

最终结果为dp[Bx][By]。

sol()为初始时做的DFS的做法,sol1()是DP正确做法

代码
#include <iostream>
using namespace std;
int bx, by, hx, hy;
int ans = 0;
bool flag[30][30] = { false };
long long int result[30][30] = { 0 };
//这是一道dp问题,不是dfs,会超时
bool check(int x, int y) {
    if (x > bx || y > by || (hx == x && y == hy) || (x == hx - 1 && y == hy - 2) || (x == hx - 1 && y == hy + 2) || (x == hx - 2 && y == hy - 1) || (x == hx - 2 && y == hy + 1)
        || (x == hx + 1 && y == hy - 2) || (x == hx + 1 && y == hy + 2) || (x == hx + 2 && y == hy - 1) || (x == hx + 2 && y == hy + 1)) {
        return false;
    }
    return true;
}

void sol(int x, int y) {
    if (x == bx && y == by) {
        ans++;
        return;
    }
    if (check(x, y)) {
        sol(x + 1, y);
        sol(x, y + 1);
    }
}


//递推公式 dp[i][j]=dp[i-1][j]+dp[i][j-1]

int dhx[8] = { 1,2,1,2,-1,-2,-1,-2 };
int dhy[8] = { 2,1,-2,-1,2,1,-2,-1 };
void sol1() {
    flag[hx][hy] = 1;
    int index = 0;
    for (index=0; index < 8; index++) {
        if ((hx + dhx[index] >= 0) && (hx + dhx[index] <= bx) && (hy + dhy[index] >= 0) && (hy + dhy[index] <= by)) {
            flag[hx + dhx[index]][hy + dhy[index]] = 1;
            
        }
    }

    index = 0;
    while (!flag[0][index]&&index<=by) {
        result[0][index++] = 1;
    }
    index = 0;
    while (!flag[index][0]&&index<=bx) {
        result[index++][0] = 1;
    }
    for (int i = 1; i <= bx; i++) {
        for (int j = 1; j <= by; j++) {
            if (!flag[i][j]) {
                result[i][j] = result[i - 1][j] + result[i][j - 1];
            }
            else {
                result[i][j] = 0;
            }
        }
    }
}

int main() {
    cin >> bx >> by >> hx >> hy;
        
        //sol(0, 0);
    sol1();
    cout << result[bx][by] << endl;
    
    return 0;
}  

 

 

 

 

 

posted @ 2021-04-07 18:33  徐不二  阅读(75)  评论(0)    收藏  举报