「题解」:[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\n",dist[en]);
    return 0;
}

原文地址:https://www.cnblogs.com/xingmi-weiyouni/p/11620709.html

时间: 2024-08-30 02:40:22

「题解」:[loj2763][JOI2013]现代豪宅的相关文章

「题解」kuangbin 最小生成树

POJ-1251 Jungle Roads (水题,%c) POJ-1287 Networking (水) POJ-2031 Building a Space Station (%f浮点数尴尬精度,两球间距离) POJ-2421 Constructing Roads (一些边已建好,简单处理一下) ZOJ-1586 QS Network (处理一下边权) HDU-1233 还是畅通工程 (水) HDU-1875 畅通工程再续 (浮点数,条件连边) HDU-1301 Jungle Roads (重

「题解」「美团 CodeM 资格赛」跳格子

目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞定,最后无奈 \(90pts\) . 然而 \(T2\) 想到很多很奇怪的做法,结果正解在 \(28min\) 之内做出... 结果 \(T3\) 是本人最不擅长的伪期望,直接跳过,啥都没得. 来水一发 \(T1\) 的题解... 题目描述 点这里 考场思路 其实并没有什么十分特别的思路,就是一通乱

「题解」:世界线

问题 A: 世界线 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 我刚学完bitset就考了???然而我赛时并没有想到是bitset…… 话说我bitset还是没有颓完啊赶紧去补一波时空复杂度…… bitset优化暴力(据某诺神说这是bitset果题??) 注意dfs的时侯如果目标节点已经搜过了直接用当前节点的bitset或上目标节点的bitset值即可. 还有$6e4×6e4$会炸空间.开一个$6e4×3e2$的然后一半一半跑即可. 至于怎么跑一半,直接判断和

「题解」:联

问题 A: 联 时间限制: 2 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 解法1:离散化+线段树. 1e18的数据范围直接离散化掉所有的l和r,加一个映射数组表示间距即可. 线段树维护区间和,扫0的时候判定子树和等不等于子树大小. 维护两个标记:lazy(将一个区间赋值成什么).xr(是否异或整个区间)跑就完了. (我会说我沉迷解法二而解法一是水的么 感谢Larry提供的优质讲解及代码) #include<bits/stdc++.h> #define int long l

「题解」:X国的军队

问题 A: X国的军队 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 简单贪心. 按照存活的士兵数量(即参加战斗的士兵数量减去阵亡的士兵数量)排序. 若存活士兵数量相同则按照参与战斗的士兵数量排序. 顺序扫一遍统计答案. #include<bits/stdc++.h> #define int long long #define rint register int #define read(A) A=init() using namespace std; inl

「题解」:Simple

问题 A: Simple 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 不算数学的数学题?? 直接枚举会重.$60%$两种算法:1.无脑$vis$数组记录.2.$exgcd$解方程判定是否有解. $100%$:首先考虑特殊情况:$n$.$m$互质. 我们设$n*x+m*y=z$,考虑枚举$y$和$x$,不难发现,当$y>=x$的时候均能找到一个$y'$使得$n|(y-y')$. 于是会出现重复.因此只需枚举$y([0,n-1])$,计算贡献即可. 对于一般情况,

「题解」:e

问题 B: e 时间限制: 2 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 话说一天考两个主席树这回事…… 正解可以叫树上主席树??(脸哥说也叫主席树上树???) 对于树上的每一条链建主席树,支持链上查询前驱和后继. 对于所有的$p[i]$,他说怎么得到就按他说的做就好,然后求所有$p[i]$的$LCA$. 对于每个$p[i]$到$LCA$的链上查一次$r$的前驱和后继更新答案即可. 注意:参数不要传反.别一个特判把自己判掉.pre和nxt的代码不要粘贴,粘贴了不要忘记改掉内

「题解」:毛一琛/$cow$ $subsets$

问题 A: 毛一琛/$cow$ $subsets$ 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 题名貌似是个大神??看起来像是签到题然后就死了. 首先$O(3^n)$算法显然.也显然过不去$20$的测试点. 正解是赫赫有名的$meet$ $in$ $the$ $middle$算法.数据在40以内的都能用$meet$ $in$ $the$ $middle$?? 对于两半路径,可以拼起来并且构成合法答案的条件是两人获得的分数相同. 所以一个比较聪明的办法是,不去记

「题解」:毛三琛

问题 C: 毛三琛subset 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 一眼题解随机化,吓够呛.一句话题解:二分答案加剪枝. 外层枚举$x$,然后二分答案暴力$check$.如果当前答案对于x的check失败就continue, 因为在当前的x中不可能找到比当前答案更优秀的解.加clock卡常可以A. 貌似不需要看脸.毕竟我这个非洲人都一遍A了.复杂度$O(np+nlognlogp)$. 代码:(ps.$¥$神指出了我代码的缺陷:其实在外面直接赋值可以少一