当前位置: 首页 > news >正文

动态规划----过河卒

[NOIP2002 普及组] 过河卒_牛客题霸_牛客网

更新:之前的方法很笨,需要控制边界调节,还要自己开辟数组,有一个比较巧的方法,从dp[1][1]开始作为0,0点。人为制造一个虚拟边界。把棋盘整体往右、往下错开一格,从 (1,1) 开始算真正的棋盘,在外面留出一圈安全缓冲区(下标 0 行 / 0 列),所有转移都合法。有以下几点:1.题目说了不会超过20,所以可以提前开一个数组,全局的数组自动初始化为0。2.让dp[0][1]为1,可以使程序根据转移方程自动推导dp[1][1],也就是初始值。初始化情况如下:

      j →
      0   1   2   3   4
i ↓  ---------------------
0 |   0   1   0   0   0
1 |   0   ?   ?   ?   ?
2 |   0   ?   ?   ?   ?
3 |   0   ?   ?   ?   ?
4 |   0   ?   ?   ?   ?

  • dp[0][1] = 1

  • 这样在更新 dp[1][1] 时,dp[1][1] = dp[0][1] + dp[1][0] = 1 + 0 = 1 

  • 不会访问负下标;

  • 同理,dp[i][0] 默认全为 0(因为数组初始为全 0),自然就能处理“左边界”,同时在处理第一行时,也能处理“上边界”。

#include<iostream>
using namespace std;int n,m,x,y;
long long dp[25][25];int main()
{cin>>n>>m>>x>>y;dp[0][1] = 1;x += 1; y += 1;for(int i = 1;i <= n+1;i++){for(int j = 1;j <= m+1;j++){if(i != x && j != y && abs(i - x) + abs(j - y) == 3|| (i == x && j == y)){dp[i][j] = 0;}else{dp[i][j] = dp[i-1][j] + dp[i][j-1];}}}cout<<dp[n+1][m+1];return 0;
}

可以扩展到其它 DP 问题(如路径、网格、棋盘等),方便第一行、第一列的状态转移。

---------------------------------------------------------------------------------------------------------------------------------

有几点需要注意

1.由于我没玩过象棋,所以不知道马走日。其实就是马只能从日的一个对角到另一个对角,横的或者竖的日都可以,其次马可以到的点,是不可以走过去的;

2.虽然题中给的是6,6,但是开数组时要开6+1,6+1,因为数组是这条线,不是棋盘!

假设dp[i][j]为到第i行第j列点的路径总数。初始状态,我们假

dp的第一行和第一列都是1(我一开始是这么想的,后来有错误,但其实应该考虑如果第一行和第一列有马可以到的点的情况)。然后分析状态转移方程,一个点,到他的方向只有左边或者上面,所以到该点的路径数就是从上下来的点和从左过来的点的路径之和:dp[i][j]=dp[i-1][j]+dp[i][j-1]。注意,马可以到到的点的dp直接赋值成0!因为不可到达该点,所以路径为0。

bool is_enemy(int i, int j, int c, int d) {if (i == c && j == d)return true;else if (abs(i - c) + abs(j - d) == 3 && i != c && j != d)return true;elsereturn false;
}int main() {int a, b, c, d;while (cin >> a >> b >> c >> d) { // 注意 while 处理多个 casevector<vector<long long>> dp;vector<long long> v1;for (int i = 0; i < b + 1; i++) {v1.push_back(1);//有问题}dp.push_back(v1);for (int i = 1; i < a + 1; i++) {vector<long long> v(b + 1, 0);v[0]=1;//有问题for (int j = 1; j < b + 1; j++) {if (!is_enemy(i, j, c, d)) {v[j] = dp[i - 1][j] + v[j - 1];} else {v[j] = 0;}}dp.push_back(v);}cout << dp[a][b] << endl;}
}

这是我一开始写的,但这里其实是有问题的,就是我开始说的,第一行和第一列应该会有马到的点,这点没有考虑,其次,如果这两个地方有一个点是马到的点的话,它往后的点都不可达,即往后所有点的dp都要为0!!!!!

bool is_enemy(int i, int j, int c, int d) {if (i == c && j == d)return true;else if (abs(i - c) + abs(j - d) == 3 && i != c && j != d)return true;elsereturn false;
}int main() {int a, b, c, d;while (cin >> a >> b >> c >> d) { // 注意 while 处理多个 caseint dealut=1;vector<vector<long long>> dp;vector<long long> v1;for (int i = 0; i < b + 1; i++) {if(is_enemy(0, i, c, d))dealut=0;v1.push_back(dealut);}dp.push_back(v1);int value=1;for (int i = 1; i < a + 1; i++) {vector<long long> v(b + 1, 0);if(is_enemy(i,0,c,d))value=0;v[0]=value;for (int j = 1; j < b + 1; j++) {if (!is_enemy(i, j, c, d)) {v[j] = dp[i - 1][j] + v[j - 1];} else {v[j] = 0;}}dp.push_back(v);}cout << dp[a][b] << endl;}
}

再说一句,这里为什么不用int作为dp中值的类型,因为有一个测试例子,路径数达到了56477364570,int为 −2,147,483,648∼2,147,483,647,放不下,所以这里要用longlong类型。

http://www.dtcms.com/a/491531.html

相关文章:

  • 2025-10-15 ZROJ25普及联考day12 赛后总结
  • 工控人如何做自己的网站网页版微信文件传输助手
  • 南京网站建设网站高端网站建设 案例
  • Qt程序高分辨界面显示不正常解决办法
  • 如何下载Windows 11安装文件
  • Java 大视界 -- 基于 Java 的大数据隐私计算在医疗影像数据共享中的实践探索
  • 版本管理:Git Large File,二进制文件追踪?
  • 网站开发课程报告心得中国十大装修公司品牌排行榜
  • 广告设计培训机构哪家好南京谷歌seo
  • 企业活动网站创意案例铜陵市建设局网站
  • 计算机操作系统——文件系统的全局结构
  • 万万州州微微网站网站建建设设网页设计实训报告主要内容
  • pwn.college之Cryptography模块
  • wordpress 点评类网站找人做网站注意什么
  • 桥接模式详解
  • 【入门级-算法-3、基础算法:二分法】
  • 配置串口与应用
  • python中的浮点数运算
  • 如何解决Redis缓存“数据一致性“问题?
  • 一般的域名可以做彩票网站吗高校网站网页设计
  • 第一家中文商务网站服装设计网页制作素材
  • IDEA从jdk8换成jdk17后又还原的那些事
  • 网站建设解决方案有哪些wordpress如何定义锚
  • 机器人逆动力学及其应用
  • 微服务之SpringCloud Alibaba(注册中心Nacos)
  • NewStarCTF2025-Week2-Misc
  • 网站建设情况专业全网优化
  • 在JavaScript / HTML中,浏览器中如何使用js判断是否为苹果平台
  • 磁盘-IO
  • Spring Boot 外部化配置最佳实践指南