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

飞往大厂梦之算法提升-7

今天主要给大家分享dfs以及动态转移中的数位dp问题,这两类问题可以很好地提升我们的思维。希望能对大家有所帮助。

第一题:

问题描述

小蓝有一天误入了一个混境之地。

好消息是:他误打误撞拿到了一张地图,并从中获取到以下信息:

  1. 混境之地的大小为 n⋅m,其中 # 表示这个位置很危险,无法通行,. 表示道路,可以通行。
  2. 他现在所在位置的坐标为(A,B) ,而这个混境之地出口的坐标为 (C,D) ,当站在出口时即表示可以逃离混境之地。
  3. 混境之地中有 kk 个单向传送门,当你站在上面时,你可以选择消耗 pi​ 点能量,从当前点(x1i​,y1i​) 传送至 (x2i​,y2i​) ,同样你也可以选择不通过该传送门。

坏消息是:小蓝仅剩下 E点能量。

小蓝可以往上下左右四个方向行走,每行走一步,消耗一点能量。

小蓝想知道他能否逃离这个混境之地,如果可以逃离这里,请你帮他计算一下,他最多可以剩下多少能量,如果无法逃离则输出 -1 。

输入格式

第 1行输入两个正整数 n,m ,表示混境之地的大小。

第 2 行输入四个正整数 A,B,C,D ,表示小蓝当前所在位置的坐标,以及混境之地出口的坐标。

第 3行至第 n+2 行,每行 m 个字符,表示混境之地的地图,其中 # 表示为危险的地方, . 表示普通的道路。

第 n+3 行输入一个正整数 kk ,表示传送门的数量。

接下来 k 行,每行五个正整数 x1i​,y1i​,x2i​,y2i​,pi​ ,表示(x1i​,y1i​) 处有一个单项传送门,可以消耗 pip点能量使用该传送门从 (x1i​,y1i​) 传送至(x2i​,y2i​) 。

最后一行输入一个 E ,表示小蓝剩下的能量值。

输出格式

输出数据共一行为一个整数:

  • 若小蓝可以逃离混境之地,则输出他最多可以剩下的能量值。
  • 若小蓝无法逃离混境之地,则输出 -1 。

输入案例:

5 5
1 1 2 5
...#.
..#..
#...#
...#.
.....
2
1 2 5 3 1
1 3 1 5 2
7

输出案例:

2

代码部分:

#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
int n, m, a, b, c, dd, k, e;
const int N = 55;
pair<int, int> g[N][N];
char mp[N][N];
int vis[N][N];
int d[N][N], h[N][N];
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};void dj() {memset(d, 0x3f, sizeof d);priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, greater<pair<int, pair<int, int>>> > q;d[a][b] = 0;q.push({0, {a, b}});while (!q.empty()) {int x = q.top().y.x;int y = q.top().y.y;int z = q.top().x;q.pop();if(vis[x][y])continue;vis[x][y]=1;for(int i=0;i<4;i++){int nx=x+dx[i],ny=y+dy[i];if(nx<1||ny<1||nx>n||ny>m||mp[nx][ny]=='#'||vis[nx][ny])continue;if(d[nx][ny]>d[x][y]+1){d[nx][ny]=d[x][y]+1;q.push({d[nx][ny],{nx,ny}});}}if(h[x][y]){int nx=g[x][y].x;int ny=g[x][y].y;if(d[nx][ny]>d[x][y]+h[x][y]){d[nx][ny]=d[x][y]+h[x][y];q.push({d[nx][ny],{nx,ny}});}}}
}int main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin >> n >> m;cin >> a >> b >> c >> dd;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)cin >> mp[i][j];cin >> k;while (k--) {int x1, x2, y1, y2, w;cin >> x1 >> y1 >> x2 >> y2 >> w;g[x1][y1] = {x2, y2};h[x1][y1] = w;}cin >> e;dj();if (d[c][dd]>1e9) cout << "-1";else cout << e - d[c][dd];return 0;
}

这是一道经典的路径问题,这道题跟我们之前做的区别就在于,这道题路径中并没有直接的钥匙或者圣水什么,所以并不是简单的求解里面的某一点到入口或者出口的距离。所以这道题需要用priority_queue进行求解。

这里有几个注意点⚠️:

1.priority_queue使用小根堆,即更小的数在前面。

2.注意if(h[x][y])的判断要在for外面,这里是我一开始一直做错的原因。

3.make_pair的输入方式(c++11版本)

第二题:

问题描述

从前有一个国王,他十分热爱数字,他认为数字的优雅程度可以从它们的位数上体现出来。数字的“优雅程度”越高,就越能够吸引他的眼球。他定义,只要一个正整数的十进制表示中包含不超过 3 个非零数字,就被认为是优雅的数字。例如,3、2000、123 是优雅的数字,而 4321、12306、120086 则不是。

这个国王曾经让他的数学家寻找一定范围内所有的优雅数字。但这些数学家并不满足于简单地列出这些数字,他们想要创造一个故事,使得这些数字更加有生命力、更加有意义。于是他们提出了一个挑战:给出一个数字区间,计算其中有多少个优雅的数字。你能够帮助这些数学家完成他们的任务吗?

输入格式

输入包含多个测试用例。

每个测试用例的第一行包含一个整数 T(1≤T≤102),表示要考虑的数字区间的数量。

接下来 T行,每行包含两个整数 Li​ 和 Ri(1≤Li​≤Ri​≤1018),表示一个区间的左右端点。

输出格式

对于每个测试用例,输出一个整数,表示相应区间中优雅数字的数量。

输入案例:

2
1 1000
11111 22222

输出案例:

1000
552

代码部分:

#include <bits/stdc++.h>
using namespace std;
using ll =long long;
ll dp[20][2][20];
int a[20];
ll dfs(int pos,bool snt,bool limit,int cnt){if(pos<0)return (int)(cnt<=3);if(!limit&&dp[pos][snt][cnt]!=-1)return dp[pos][snt][cnt];ll res=0;int up=limit?a[pos]:9;for(int i=0;i<=up;i++){res+=dfs(pos-1,snt||(i>0),limit&&(i==up),cnt+(i>0));}if(!limit)dp[pos][snt][cnt]=res;return res;
}ll f(ll b){int pos=0;while(b){a[pos++]=b%10;b/=10;}return dfs(pos-1,false,true,0);
}
int main()
{int t;cin>>t;while(t--){memset(dp,-1,sizeof(dp));ll a,b;cin>>a>>b;cout<<f(b)-f(a-1)<<'\n';}return 0;
}

这道题是数位dp的标准问题,关于数位dp大家可以看看我之前的文章,有专门做过这一部分的题解,大家可以多多了解了解。

对于数位dp要注意⚠️:

1.limit==false时进行剪纸

2.a[n]是从低位开始存放的,但是从高位开始剪枝。

3.结果注意要是没有0,要减去1,看题意具体的描述。

第三题

问题描述

在一个神秘的魔法世界中,有一位年轻的魔法学徒叫做小李。小李是一个非常聪明的学徒,他一直在学习各种魔法,包括数学魔法。

有一天,小李找到了一本古老的魔法书,书中记载了很多神秘的数学问题和解法。小李对其中一个问题非常感兴趣,它是这样的:给定两个正整数 n 和 k,请计算在 1 到 n 中有多少个数的各位数字之和是 k 的倍数。

小李思考了很久,但是一直没有找到解决这个问题的方法。他知道这个问题与数位魔法有关,但是他不知道具体如何操作。于是,小李求助了你。

现在,请你帮助他编写一个程序,来解决这个数学问题。由于这个问题的答案很大,你只需要将答案对 998244353 取模的结果给他即可。

输入格式

输入共一行,包含两个正整数 n和 k(1≤n≤101000,1≤k≤100)。

输出格式

输出一个整数,表示在 1到 n 中有多少个数的各位数字之和是 kk 的倍数,对998244353 取模的结果。

输入案例:

20 4

输出案例:

4

代码部分:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll p=998244353;
const int N=1003;
map<ll,ll>dp[N];
int a[N];
int k;
string n;
ll dfs(int pos,int limit,ll sum){if(pos<0)return (sum==0);if(!limit&&dp[pos].find(sum)!=dp[pos].end())return dp[pos][sum];ll res=0;int up=limit?a[pos]:9;for(int i=0;i<=up;i++){res+=dfs(pos-1,limit&&(up==i),(sum+i)%k)%p;}if(!limit)dp[pos][sum]=res;return res;
}int main()
{cin>>n>>k;for(int i=0;i<n.size();i++){a[n.size()-i-1]=n[i]-'0';}cout<<dfs(n.size(),1,0)-1<<'\n';return 0;
}

这道题思路与上一条一样,但是注意当题目数值较大时,可以选择用map<int,int>dp[][]来存储数据,这样可以让没有的值为空值。

第四题:

问题描述

给定 N,K,询问有多少个 N 的全排列,满足有 K个逆序对,答案对998244353 取模。

输入格式

第一行包含 2 个正整数N,K。

输出格式

输出共 1 行,包含 1 个整数,表示最终答案,答案对 998244353 取模。

输入案例:

3 1

输出案例:

2

代码部分:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=5e2+10;
ll dp[N][N];
const int mod = 998244353;
int main()
{int n,k;cin>>n>>k;for(int i=1;i<=n;i++){dp[i][0]=1;}for(int i=1;i<=n;i++){for(int j=1;j<=k;j++){for(int l=0;l<i&&l<=j;l++){dp[i][j]=(dp[i][j]+dp[i-1][j-l])%mod;}}}cout<<dp[n][k];return 0;
}

理解这道题就可以更好地理解dp的实质,前后状态转移的实质,而不是死记硬背,这道题虽然简单,但是却可以很好地考察你对于动态规划转移的本质理解。

好了,今天的分享就到这里,希望大家可以多多关注博主,后续我也将继续分享相关内容。

相关文章:

  • 郑州做响应式网站/百度刷排名seo软件
  • 新疆5g基站建设/在百度上怎么打广告
  • 如何建设网站挣钱/品牌传播策略
  • 设计公司网站套餐/优化教程网下载
  • 网站建设公司网络服务/国内推广平台
  • 公司营销网站制作/seo裤子的关键词首页排名有哪些
  • Vue 列表过滤:语法与注意事项详解
  • Docker知识点汇总——AI教你学Docker
  • LINUX 623 FTP回顾
  • C++面向对象3——C++面向对象的权限、引用与指针
  • H5新增属性
  • logstash读取kafka日志写到oss归档存储180天
  • 2025年CSS最新高频面试题及核心解析
  • 边缘-云协同智能视觉系统:实时计算与云端智能的融合架构
  • Linux系统能ping通ip但无法ping通域名的解决方法
  • LeetCode热题100—— 160. 相交链表
  • [附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+Vue实现的校园二手交易平台管理系统,推荐!
  • Threejs实现 3D 看房效果
  • 【kubernetes】--controller(deployment)
  • 洛谷 P10379 [GESP202403 七级] 俄罗斯方块-普及/提高-
  • 使用Vue重新构建应用程序
  • UP COIN:从 Meme 共识走向公链与 RWA 的多元生态引擎
  • 浅析std::atomic<T>::compare_exchange_weak和std::atomic<T>::compare_exchange_strong
  • Docker 与 Containerd 交互机制简单剖析
  • Apache SeaTunnel Spark引擎执行流程源码分析
  • 刀客doc:阿里巴巴集团品牌部划归集团公关管理