当前位置:首页 > 经验 >

重力球怎么玩视频讲解(平衡球怎么玩的视频)

来源:原点资讯(www.yd166.com)时间:2022-11-09 10:52:34作者:YD166手机阅读>>

原题链接

题目大意是任意放置两个重力球,可以多次切换重力方向,(上下左右四个方向),问两个重力球相遇的最小重力调整次数。

重力球怎么玩视频讲解,平衡球怎么玩的视频(1)

示例

如上图,若绿圆为重力球的初始位置,则至少调整三次重力方向,可以是两个重力球相遇。该题的难点在于需要查询多次,每次查询重力球的初始位置都会变化,但地图不变。

前置知识

该题前置知识主要包括BFS广度优先搜索多源BFS最短路

algorithm 1(BFS)

单次询问,我们可以使用BFS外加模拟重力球移动来求解,首次相遇时的移动次数即为答案。在多次询问下,如果每次都需要BFS必然会TLE。由于重力球在路过的位置不会停留,实际上我们不必每次都模拟重力球的路线,而是预计算并缓存重力球在某点x上通过改变重力向上、下、左、右可以到达的某点y。即使这样依旧会TLE,我们需要仔细想想其他的方法。

algorithm 2(多源BFS)

正难反易,我们逆向考虑一下问题。

对于相遇重力次数改变的问题,A,B两点到O相遇重力改变次数,可从O为起点反向得到。对某一相遇点作为初始node进行BFS遍历,则可计算出任意一对可停留初始点到该相遇点的最少重力改变次数。但是两个重力球的相遇点可能不止一个,所以我们要在二者所有可能的相遇点中,去寻找最少的重力改变次数。如果还是需要多次BFS,那逆向考虑问题好像也没啥作用。

若同时对多个相遇点进行BFS遍历,可将众多相遇点一次性添加到BFS队列中,作为BFS的超级node,再进行BFS,需要边放松操作,用新最优解覆盖原有最优解,并插入新的点对。则可计算出任意一对可停留初始点能够在某点时最少重力切换次数!

可读代码

我在代码中关键的位置都加入了注释,包括初始化障碍,生成停留图邻接表,O(1)查询滚动位置,多源DFS等。以下代码参考目前洛谷最佳算法Rainer在此感谢!我做了大量可读性优化,牺牲了部分性能,不过还能挺进TOP3。

代码中一部数组长度为maxn*8,仔细分析,重力球除了初始位置之外,只能停留在四边外围墙内侧一格或障碍物的上下左右四格。对于n*n网络里面有m个障碍物,则重力球停靠的位置不超过4(n m),若m<=n,则不超过8n。

#include <bits/stdc .h> using namespace std; #define ll long long const int maxn=250 10; const int dx[]={0,-1,0,1}; const int dy[]={-1,0,1,0}; const int inf=1e8; int n, m, q, nc=0; bool block[maxn][maxn]; int node[maxn*8][2], node_id[maxn][maxn], roll[maxn][maxn][4]; vector<int> edge[maxn*8][4]; int dis[maxn*8][maxn*8];/*node_id,node_id,dist*/ int que[maxn*8*maxn*8][2], nq=0; /*初始化障碍物,外围四边*/ inline void init_block() { scanf("%d%d%d",&n,&m,&q); int x,y; for (int i=1; i<=m; i ) scanf("%d%d",&x,&y), block[x][y]=true; for (int i=0;i<=n 1;i ) block[0][i] = true; for (int i=0;i<=n 1;i ) block[n 1][i] = true; for (int i=0;i<=n 1;i ) block[i][0] = true; for (int i=0;i<=n 1;i ) block[i][n 1] = true; } /*障碍物上下左右创建结点,统计个数,生成id*/ inline void init_node(){ for (int i=1; i<=n; i ) for (int j=1; j<=n; j ) if (!block[i][j]) { bool flag = false; for (int k=0; k<4; k ) if (block[i dx[k]][j dy[k]]) flag = true; if (flag) node[ nc][0]=i, node[nc][1]=j, node_id[i][j]=nc; } } /*生成邻接表*/ inline void init_edge(){ /*利用roll数组缓存,用于后面快速查询滚动位置*/ for (int i=1; i<=n; i ) for (int j=1; j<=n; j ) if (!block[i][j]) { for (int k=0; k<2; k ) {/*处理上滚,左滚*/ int x=i dx[k], y=j dy[k]; if (!block[x][y]) roll[i][j][k]=roll[x][y][k]; else roll[i][j][k]=node_id[i][j]; if (node_id[i][j]) edge[roll[i][j][k]][k].push_back(node_id[i][j]); } } for (int i=n; i>=1; i--) for (int j=n; j>=1; j--) if (!block[i][j]) { for (int k=2; k<4; k ) {/*处理下滚,右滚*/ int x=i dx[k], y=j dy[k]; if (!block[x][y]) roll[i][j][k]=roll[x][y][k]; else roll[i][j][k]=node_id[i][j]; if (node_id[i][j]) edge[roll[i][j][k]][k].push_back(node_id[i][j]); } } } inline void bfs(){ for (int i=1; i<=nc; i ) for (int j=1; j<=nc; j ) dis[i][j]=inf; for (int i=1; i<=nc; i ) { dis[i][i]=0; que[ nq][0]=i; que[nq][1]=i; //队尾插入超级源点(起点id,终点id); } int cur=1; while (cur<=nq){ int x=que[cur][0], y=que[cur ][1], d=dis[x][y];//队首出列 ,目前为止x,y两点最少次数 for (int i=0; i<4; i )//起初xx,yy相等 for (int xx:edge[x][i])//xx可通过一次i向滚动到x for (int yy:edge[y][i]){//yy可通过一次i向滚动到y if (dis[xx][yy]>d 1) {//边放松 printf("pa:(%d,%d)pb:(%d,%d)na(%d,%d)nb(%d,%d)\n", node[x][0],node[x][1],node[y][0],node[y][1], node[xx][0],node[xx][1],node[yy][0],node[yy][1]); dis[xx][yy]=dis[yy][xx]=d 1; //同时更新正反向边更新 que[ nq][0]=min(xx,yy); que[nq][1]=max(xx,yy);//正向边插入队列,用于更新其他使用该node的dis数据 } } } } inline void query() { int ans; while (q--){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if (x1==x2&&y1==y2) ans=0; else { ans=inf; for (int i=0; i<4; i ){ int x=roll[x1][y1][i], y=roll[x2][y2][i];//滚动一次,快速查询滚动位置 ans=min(ans, dis[x][y] 1); } if (ans>=inf) ans=-1; } printf("%d\n", ans); } } int main() { //freopen("test.in", "r", stdin); init_block(); init_node(); init_edge(); bfs(); query(); return 0; }后记

网上没看到太好的题解,索性自己先研究一下,自当备课了。就算是入门组的题想要拿满分也是真心不容易,令人感叹!如果对您有帮助,点个赞吧。不过我内心也清楚,在头条上看这种文章的人很少。

栏目热文

握力球怎么玩(练了一年握力器变化)

握力球怎么玩(练了一年握力器变化)

大家好,我是少庸,一个很容易满足,品味一般,文笔稀烂,肤浅而快乐的普通打工人,只是希望通过在头条记录下自己买过的那么多东...

2022-11-09 11:00:50查看全文 >>

重力球奶瓶的优缺点(十大最良心母婴产品)

重力球奶瓶的优缺点(十大最良心母婴产品)

之前测评新生儿奶瓶的时候测过一款allobaby芬贝的奶瓶你们还记得伐?因为整体测评下来数据非常漂亮:而且还有能调节奶流...

2022-11-09 10:42:26查看全文 >>

重力球的教程视频(重力球吸管怎么组装)

重力球的教程视频(重力球吸管怎么组装)

同学们好,我是王尚老师,《初中物理七百讲》视频录制者,这篇文章向同学们分享:初二物理下册视频教程160讲第7章《力》第3...

2022-11-09 10:57:13查看全文 >>

重力球训练方法(重力球核心力量训练)

重力球训练方法(重力球核心力量训练)

药球是一种重力球,它能很好的辅助训练者达到锻炼目标,它的变化形式很多,除了加强核心力量以外,也能提高肌肉的耐力、爆发力,...

2022-11-09 10:27:36查看全文 >>

手摇重力球原理(手摇球的原理)

手摇重力球原理(手摇球的原理)

装修能花50万,说明屋主已经开始追求生活品质了,很多东西都讲究多功能、高颜值。但让人懊恼的是,有时候,即便你花了大价钱,...

2022-11-09 11:08:45查看全文 >>

握力球的正确使用方法(握力球标准动作图解)

握力球的正确使用方法(握力球标准动作图解)

现在年轻人生活压力大,生活节奏快,生活没有规律。各种健康问题也随之而来,有人是需要多用点时间来锻炼运动,缓解下这样的工作...

2022-11-09 10:50:14查看全文 >>

腕力球转不起来(腕力球转不起来了是哪里出了问题)

腕力球转不起来(腕力球转不起来了是哪里出了问题)

整天坐在电脑前工作的我们,经常肩颈脖子酸痛,想要健身却又懒得动,因为缺乏锻炼不知不觉地产生了“鼠标手”和“手机手”。虽然...

2022-11-09 10:58:26查看全文 >>

腕力球有用吗(腕力球使用一个月效果)

腕力球有用吗(腕力球使用一个月效果)

作者:会跑的葡萄糖 整天坐在电脑前工作的人们~想要健身的人们~是不是经常被自己的惰性打败,根本不想去健身?今天就来晒一个...

2022-11-09 10:30:23查看全文 >>

腕力球怎么转起来图解(腕力球正确操作方法)

腕力球怎么转起来图解(腕力球正确操作方法)

前几期小编给大家推荐了新产品75派智能腕力球Q20,今天就给大家演示一下如何玩活ta。收到75派智能腕力球Q20的第一时...

2022-11-09 11:06:01查看全文 >>

减压球怎么玩(自己做的减压球)

减压球怎么玩(自己做的减压球)

现在大家都喜欢在桌面上放些休闲娱乐的小玩意,平时工作学习的间隙可以拿来放松,平时放着的时候也能够作为装饰品。市面上这类减...

2022-11-09 10:59:53查看全文 >>

文档排行