牛牛与跷跷板
抓住题目中:相邻则可以跳跃,目的是寻求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了一道题的签到选手太惭愧了)