牛牛与跷跷板
抓住题目中:相邻则可以跳跃,目的是寻求1号块到n号的最小跳跃次数
可以确定这道题的基本解法是:最短路
然后在题目的思考过程中发现,这道题的图并没有给你构造出来
那就需要从零开始构建边与边之间的关系
第一发想到的当然是暴力构建,N^2 的复杂度果然超了……
随后发现,这题居然可以贪一贪!
怎么贪呢,分两种情况:
① *:Y坐标相同时,只有贴在一起的块能相互连通,这个非常好处理
② *:Y坐标不同时,我们从Y==0算起,每次只判断Y行和Y+1的快是否互相连通,当推到最大的Y坐标是能,整个图也就构建完成了
这样做就要把每行的元素都排个序,所以就用vector数组存数据了,数组编号就是y轴坐标。
然后把最短路板子套进去就ok了
(最短路用的y总的板子,改都没改,所以说这一题关键还是在于选择什么样的构建方案)
那么看代码,细节我已经注释上去了
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
struct Node{//节点定义,分别是编号,y坐标,左右x坐标
int id,py,px1,px2;
bool operator<(const Node &M)const {return px1<M.px1;}
};
int dist[200005],n,maxr;//dist是最短路的数组,maxr是最大y坐标
bool st[200005];//最短路模板
vector<int> g[200005];//构建的邻接表
vector<Node>li[100005];//存储输入信息
void uni(int i,int j){ g[i].push_back(j); g[j].push_back(i); }//邻接表中链接i,j
int dijkstra(){//dij求最短路,模板
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > heap;
heap.push({0, 1}); // first存储距离,second存储节点编号
while (heap.size()){
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (auto i = g[ver].begin(); i != g[ver].end(); i ++){
int j = *i;
if (dist[j] > distance + 1){
dist[j] = distance + 1;
heap.push({dist[j], j});
}
}
}
return dist[n];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){//存储输入信息和记录最大y坐标
int x,y,z;cin>>x>>y>>z;
li[x].push_back({i,x,y,z});
maxr=max(maxr,x);
}
for(int i=0;i<=maxr;i++){//①*
sort(li[i].begin(),li[i].end());//每行排序
for(int j=1;j<li[i].size();j++)
if(li[i][j-1].px2==li[i][j].px1) //横向相邻即链接
uni(li[i][j-1].id,li[i][j].id);
}
for(int i = 0; i <= maxr; i++) {//②*
auto p1 = li[i].begin(), p2 = li[i + 1].begin();//p1,p2代表前后两行
while(p1 != li[i].end() && p2 != li[i + 1].end()) {//直到数完一行所有的元素
if(max(p1->px1, p2->px1) < min(p1->px2, p2->px2))
uni(p1->id,p2->id);//满足有接触,链接
if(p1->px2 <= p2->px2) p1++;//推进到下一对判断
else p2++;
}
}
cout<<dijkstra();//最短路求结果
} (太菜了我QAQ,这道题比赛时死磕3小时最后还是没做出来,只a了一道题的签到选手太惭愧了)

京公网安备 11010502036488号