{题解}[jzoj5049]【GDOI2017模拟一试4.11】腐女的生日

按照惯例

Description

给出一个二维图 已知m个矩阵覆盖部分区域 且这m个矩阵严格不相邻
在不碰到任一矩阵情况下 求给出两坐标间最短距离[曼哈顿距离]

Solution

40分做法

无视一切矩阵 求曼哈顿距离
好吧就是扯淡

100分做法

显然 不会出现“封死”的情况
而且题目求的是曼哈顿
也就是说 不可能向左走(不优秀)
有了这个结论的话…

考虑从左向右做一个扫描线 也就是顺次“推进”
可以用线段树维护一下可以走到的点所需花费
步步递进即可

另外 也很容易想到将矩阵划分成四个点
然而右边两个没有用(不会更新答案)
显然可以用队列一类的东西连边
没有环的出现
复杂度易证
请使用SPFA BFS

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define oo 2139062143
#define sqr(x) ((x)*(x))
#define abs(x) (((x)>=0)?(x):(-(x)))
#define max(x,y) (((x)>(y))?(x):(y))
#define min(x,y) (((x)<(y))?(x):(y))
#define fo(i,x,y) for (int i = (x);i <= (y);++ i)
#define fd(i,x,y) for (int i = (x);i >= (y);-- i)
#define fm(i,x) for (int i = las[x];i;i = e[i].nex)
using namespace std;
typedef double db;
typedef long long ll;
const int N = 500500,Mo = 1001000;
int n,m,tot,sx,sy;
int data[Mo],dis[Mo];
int st,fin,ind[Mo],mem[Mo];
bool vis[Mo];
struct node{
    int x,uy,dy;
}sq[N];
struct edge{
    int to,nex,v;
}e[N * 5];
int las[N];
int read()
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;
    int n=q*w;return n;
}
bool cmp(node x,node y)
{
    return (x.x < y.x)||(x.x == y.x && x.uy == sy) || (x.x == y.x && x.uy != sy && x.uy > y.uy);
}
void spfa()
{
    memset(dis,127,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[st] = 0 ;
    vis[st] = 1,data[1] = st;
    int hd = 0,tl = 1;
    while (hd ++ < tl)
    {
        int now = hd % Mo;
        int x = data[now],t;
        fm(i,x)
        {
            -- ind[t = e[i].to];
            if (dis[x] + e[i].v < min(dis[t],dis[fin])) dis[t] = dis[x] + e[i].v; 
            if (!vis[t] && ind[t] == 0)
            {
                vis[t] = true;
                data[(++ tl) % Mo] = t;
            }
        }
    }
}
void link(int x,int y,int v)
{
    e[++ tot].to = y,
    e[tot].v = v,
    e[tot].nex = las[x],
    las[x] = tot;
    ++ ind[y];
}
void linking(int y,int past,int now,int dist)
{
    dis[now] = dist;
    fo(i,past + 1,n) 
    {
        if (sq[i].dy < y && sq[i].uy > y) 
        {
            bool p = false;
            if (!mem[i]) mem[i] = ++ m,++ m,p = true;
            if(abs(sq[i].uy - y) > abs(y - sq[i].dy))
            {
                link(now,mem[i],abs(sq[i].uy - y));
                link(now,mem[i] + 1,abs(y - sq[i].dy));
            }
            else
            {
                link(now,mem[i] + 1,abs(y - sq[i].dy));
                link(now,mem[i],abs(sq[i].uy - y));
            }
            if (p)
            {
                linking(sq[i].uy,i,mem[i],dist+abs(sq[i].uy-y));
                linking(sq[i].dy,i,mem[i]+1,dist+abs(y-sq[i].dy));
            }
            break;
        }
        if (sq[i].dy == sy && sq[i].x == sx) 
        {
            if (!fin) fin = ++ m;
            link(now,fin,abs(sq[i].uy - y));
            break;
        }
    }
}
int main()
{
    freopen("bl.in","r",stdin);
    freopen("bl.out","w",stdout);
    sx = read(),sy = read(),n = read(); 

    fo(i,1,n)
    {
        int xa = read(),ya = read(),xb = read(),yb = read();
        if (xa > xb) swap(xa,xb);
        if (ya > yb) swap(ya,yb);
        sq[i].x = -- xa,sq[i].uy = ++ yb,sq[i].dy = -- ya;
    }
    sq[++ n].x = sx,sq[n].uy = sq[n].dy = sy,++ n;
    sort(sq + 1,sq + n + 1,cmp); 
    st = 1;
    int i = 1;
    m = 1;
    while (sq[i].x < 0 && sq[i].dy != 0) ++ i;
    linking(0,i,1,0);
    spfa();
    printf("%d\n",dis[fin] + sx);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值