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; }
浙公网安备 33010602011771号