当前位置: 代码迷 >> 综合 >> 洛谷题解 P1002 【过河卒】
  详细解决方案

洛谷题解 P1002 【过河卒】

热度:30   发布时间:2024-02-12 23:03:25.0

洛谷题解 P1002 【过河卒】

  • 题目
      • 题目描述
      • 输入格式
      • 输出格式
      • 输入输出样例
            • 输入
            • 输出
      • 说明/提示
  • 解题思路
  • 代码

题目

题目描述

棋盘上 A 点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。
棋盘用坐标表示,A 点 (0,0) 、B 点 (n,m) ,同样马的位置坐标是需要给出的。在这里插入图片描述
现在要求你计算出卒从 A 点能够到达 B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。

输入格式

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

输出格式

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

输入输出样例

输入

6 6 3 3

输出

6

说明/提示

对于100%的数据,1≤n,m≤20,0≤马的坐标≤20。

解题思路

一道dp,即动态规划,又名动规题,
dp题目最主要是找出状态转移方程,
这道题可以根据样例模拟一下 , 就可以求出状态转移方程了。

步骤大概是这样的:
以A表示A点 , B是B点, M是马的位置, X是被马拦着不能走的点。(别告诉我你们连马走"日"字都不知道)

 A 0 0 0 0 0 00 0 X 0 X 0 00 X 0 0 0 X 00 0 0 M 0 0 00 X 0 0 0 X 00 0 X 0 X 0 00 0 0 0 0 0 B

其中每个点的值代表的是当前这个点会有几条路径用过这个点。(路径指的是从A到B的路径)

 1 1 1 1 1 1 11 2 X 1 X 1 21 X 0 1 1 X 21 1 1 M 1 1 31 X 1 1 0 X 31 1 X 1 X 0 31 2 2 3 3 3 6

这样很容易能看出来,
f[i][j]这个点 , 从(0,0)位置到B点 , 会经过他这个点的路线有:

f[1][1] = 1
f[i][j] = f[i-1][j] + f[i][j-1]

但是这个方程是推不出结果的 , 因为这样 A 点会在一开始的时候被覆盖成0!
所以修改以后的方程就是

f[1][1] = 1
f[i][j] = max (f[i-1][j] + f[i][j-1] , f[i][j])

当然还有不用max函数的转移方程

f[1][0] = 1
f[i][j] = f[i-1][j] + f[i][j-1]

f[1][1]这个点通过从f[1][0]这个点直接转移过来,
因为转移方程的时候需要 i-1j-1
而初始化被马挡住的位置的时候会有 i-2, j-2 ,
所以如果不从 2 开始就会因数组越界而 WA 一个点
从 2 开始就是把每个点的坐标都加了 2 而已

另外题目说明写着

结果可能很大!

但是 unsigned long long 就可以过去

代码

#include<bits/stdc++.h>//万能头文件
using namespace std;
const int fx[] = {0, -2, -1, 1, 2, 2, 1, -1, -2};
const int fy[] = {0, 1, 2, 2, 1, -1, -2, -2, -1};
//马可以走到的位置
int bx,by,mx,my;
unsigned long long f[30][30];//f[i][j]代表从A点到(i,j)会经过的线路数
bool s[25][25];//判断这个点有没有被马盯着
int main()
{cin >> bx >> by >> mx >> my;bx += 2; by += 2; mx += 2; my += 2;//以防越界f[2][2] = 1;//初始化s[mx][my] = 1;//标记马的位置for (int i = 1; i <= 8; i++)s[mx + fx[i]][my + fy[i]] = true;//这个点被马盯着for (int i = 2; i <= bx; i++)for (int j = 2; j <= by; j++){if(s[i][j])continue;//如果这个点被马盯着,卒就不过去f[i][j] = max(f[i][j] , f[i - 1][j] + f[i][j - 1]); //状态转移方程}cout << f[bx][by] << endl ;return 0;
}