牛牛与跷跷板

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
在这里插入图片描述
仅一行,一个非负整数,表示从第1块跷跷板移动到第n块跷跷板的最小跳跃次数。

输入:

7
0 2 4
1 0 2
0 4 6
1 7 9
0 6 8
2 3 9
2 1 3

输出:

5
在这里插入图片描述
思路: 最短路
如果全部板块都相连的话,广搜求最短路就行了。
这里的模板可能有零散的话,存图的时候优化一下就行。
先将所有板块按照从上往下,从左往右排序。
对于任意一块模板k来说,只要考虑两种联结的情况,一是右边的模板,二是下一行的模板。
同行的模板考虑k+1即可,很容易想到。
下一行的模板考虑的时候有个小贪心,对于模板k来说,下一行与它相连的模板区间如果是第[l,r]块,考虑右边的模板k+1的下一行时,只要看区间[r-1,?],不用从行头开始看。

//最短路
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
queue <int > q;
int tot=0,s=-1,z=-1;
int head[100010];
int dis[100010];
struct ban
{
    
    
    int l,r,p,y;//左右边界,所在行,编号
}a[100010];

struct ty
{
    
    
    int next,t;
}edge[2000010];
void bfs()
{
    
    
    dis[s]=1;
    q.push(s);
    while( !q.empty() )
    {
    
    
        int x=q.front();
        q.pop();
        for(int i=head[x] ;i!=-1 ;i=edge[i].next)
        {
    
    
            int y=edge[i].t;
            if(!dis[y])
            {
    
    
            q.push(y);
            dis[y]=dis[x]+1;
            }
        }
    }
}
bool cmp(ban a, ban b) //从上到下,从左到右排序
{
    
    
    if(a.y!=b.y)    return a.y<b.y;
    else return a.l<b.l;
}

void addedge(int x, int y)
{
    
    
    edge[++tot].t=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    memset(edge,-1,sizeof(edge));
    memset(head,-1,sizeof(head));

    int n;
    cin>>n;
    for(int i=1; i<=n ;i++)
    {
    
    
        cin>>a[i].y>>a[i].l>>a[i].r;
        a[i].p=i;
    }
    sort(a+1,a+1+n,cmp);
//    for(int i=1; i<=n ;i++)
//        cout<<a[i].p<<" ";
//        cout<<endl;
int l=1,r=1;
    for(int i=1; i<=n ;i++)
    {
    
    
        if(a[i].p==1 )  s=i;//存起点终点
        if(a[i].p==n )  z=i;
        //同一行的矩形联结
        if( a[i].y== a[i+1].y && a[i].r==a[i+1].l)
        {
    
    
            addedge(i,i+1);
            addedge(i+1,i);
        }
        //当前模块和下一行的模块,贪心优化联结操作

        while( l<=n && a[l].y==a[i].y ) l++;
        r=max(l,r);
        while( r<=n && a[r].y==a[l].y)  r++;
        for(; l<r ;l++)
        {
    
    

            if(a[l].l>=a[i].r)  break;
            if(a[l].r<=a[i].l)  continue;
            addedge(i,l);
            addedge(l,i);
        }
        if( l >1 )  l--;
    }
        //存完图,广搜求最短路
    bfs();
    cout<<dis[z]-1<<endl;
}

猜你喜欢

转载自blog.csdn.net/m0_53688600/article/details/113854602