• 「题解」:[loj2763][JOI2013]现代豪宅


    问题 A: 现代豪宅

    时间限制: 1 Sec  内存限制: 256 MB

    题面


    题目描述

    (题目译自 $JOI 2013 Final T3$「現代的な屋敷」)

    你在某个很大的豪宅里迷路了。这个豪宅由东西方向$M$列,南北方向$N$行的正方形房间组成。

    从西面开始第$x$列,从南面开始第y行的房间用$(x,y)$表示。

    相邻的两个房间之间都有一扇门。对于每扇门,门关上表示不可通行,门打开表示可以通行。

    当门打开时,从门一边的房间走到另一边的房间需要$1$分钟。

    另外,一些房间中有一个开关,如果连续$1$分钟按住这个开关,那么所有关上的门会打开,所有打开的门会关闭。

    现在,连接东西两个房间的门全都是关上的,连接南北两个房间的门全都是打开的。

    你现在在房间$(1,1)$,要在最短的时间内移动到房间$(M,N)$

    任务

    给出豪宅的大小M、N,以及存在开关的K个房间的位置$(x_1,y_1)、(x_2,y_2)、(x_k,y_k)$

    开始时,连接东西两个房间的门全都是关上的,连接南北的两个房间全都是打开的。

    请编写程序求出从房间$(1,1)$到达房间$(M,N)$的最短时间。不能到达时,请输出$-1$

    输入格式

    输入标准如下:

    第一行为三个以空格分开的整数$M、N、K$。

    $M$表示东西方向上房间的个数,$N$表示南北方向上房间的个数,$K$表示存在开关的房间的个数。

    接下来$K$行中的第$i$行为两个以空格分开的整数。

    表示房间$(x_i,y_i)$中存在开关。这个二元组间彼此相异。

    输出格式

    输出一行一个整数:表示移动所需的最短时间。如果不能到达房间$(M,N)$则输出$-1$。

    样例输入

    3 2 1

    1 2

    样例输出

    4

    数据范围

    $2<=M,N<=10^5,1<=K<=2*10^5,1<=X_i<=M,1<=Y_i<=N$

    题解


    考虑拆点。

    将每一个点拆成横纵两个点,横点和纵点之间连边,边权为1。(门状态转换的代价)

    对同行的$(X_i,Y_i)$的横点连边,边权为距离。对同列的$(X_i,Y_i)$的纵点连边,边权为距离。

    跑堆优化dijkstra即可。

    (JOI的代码难度相比NOIP几乎没有?/大雾)

    (然而我还是调了半个小时/大雾)

    #include<bits/stdc++.h>
    #define int long long
    #define inf 0x3f3f3f3f3f3f3f3f
    #define read(A) A=init()
    #define rint register int
    #define N 3000005
    #define M 40000006
    using namespace std;
    inline int init()
    {
        int a=0,b=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')b=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){a=(a<<3)+(a<<1)+ch-'0';ch=getchar();}
        return a*b;
    }
    int m,n,k,st,en,dist[N],cnt;
    int tot,v[M],w[M],nxt[M],first[N];
    struct node{int zb,id;}pot[N];
    struct node2{
        int x,y;
        friend bool operator < (node2 A,node2 B){
            return A.y>B.y;
        }
    };
    vector <node> hine[N],line[N];
    priority_queue <node2> QAQ;
    inline bool cmp(node A,node B){return A.zb<B.zb;}
    inline void add(int uu,int vv,int ww)
    {
        v[++tot]=vv,w[tot]=ww;
        nxt[tot]=first[uu];first[uu]=tot;
    }
    inline void dijkstra()
    {
        for(rint i=0;i<=2*k+1;i++)dist[i]=inf;
        dist[st]=0;QAQ.push((node2){st,dist[st]});
        while(!QAQ.empty())
        {
            int x=QAQ.top().x,y=QAQ.top().y; 
            QAQ.pop();
            if(y>dist[x]) continue;
            for(rint i=first[x];i!=-1;i=nxt[i])
            {
                int to=v[i],val=w[i];
                if(dist[to]>dist[x]+val)
                {
                    dist[to]=dist[x]+val;
                    QAQ.push((node2){to,dist[to]});
                }
            }
        }
    }
    signed main()
    {
        memset(first,-1,sizeof(first));
        read(m),read(n),read(k);en=2*k+1;
        for(rint i=1,xi,yi;i<=k;++i)
        {
            read(xi),read(yi);++cnt;
            line[xi].push_back((node){yi,cnt+k});
            hine[yi].push_back((node){xi,cnt});
        }
        for(rint i=1;i<=n;++i)
        {
            sort(hine[i].begin(),hine[i].end(),cmp);
            for(rint j=1;j<hine[i].size();++j)
            {
                add(hine[i][j-1].id,hine[i][j].id,hine[i][j].zb-hine[i][j-1].zb),
                add(hine[i][j].id,hine[i][j-1].id,hine[i][j].zb-hine[i][j-1].zb);
            }
        }
        if(hine[n].size())
        {
            int zhi=hine[n].size()-1;
            add(en,hine[n][zhi].id,m-hine[n][zhi].zb);
            add(hine[n][zhi].id,en,m-hine[n][zhi].zb);
        }
        for(rint i=1;i<=m;++i)
        {
            sort(line[i].begin(),line[i].end(),cmp);
            for(rint j=1;j<line[i].size();++j)
            {
                add(line[i][j-1].id,line[i][j].id,line[i][j].zb-line[i][j-1].zb),
                add(line[i][j].id,line[i][j-1].id,line[i][j].zb-line[i][j-1].zb);
            }
        }
        if(line[m].size())
        {
            int zhi=line[m].size()-1;
            add(en,line[m][zhi].id,n-line[m][zhi].zb);
            add(line[m][zhi].id,en,n-line[m][zhi].zb);
        }
        if(line[1].size())
        {
            add(st,line[1][0].id,line[1][0].zb-1);
            add(line[1][0].id,st,line[1][0].zb-1);
        }
        for(rint i=1;i<=k;++i)add(i,i+k,1),add(i+k,i,1);
        dijkstra();
        (dist[en]>=inf)?puts("-1"):printf("%lld
    ",dist[en]);
        return 0;
    }
    View Code
  • 相关阅读:
    .net系统缓存
    Android开源项目第四篇——开发及测试工具篇
    Android开源项目第三篇——优秀项目篇
    Android开源项目第二篇——工具库篇
    Android开源项目第一篇——个性化控件(View)篇
    android
    android 屏幕适配
    EditText属性
    Style与Theme
    ListView设背景
  • 原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11620709.html
Copyright © 2020-2023  润新知