1 条题解

  • 0
    @ 2025-8-24 23:01:26

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar naroto2022
    花开花谢泪满巾,羊走羊归空余情。​

    搬运于2025-08-24 23:01:26,当前版本为作者最后更新于2025-08-18 23:30:46,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    P10804 题解

    博客园查看更佳

    题面

    原题传送门

    思路

    考虑爆搜,广搜横纵向部分的横纵坐标,时间复杂度 n3n^3,原因是纵向部分左上角的纵坐标和横向部分左上角的纵坐标相同。

    但是 n3n^3 会超时,于是我们考虑优化,发现我们其实只要搜交点的横纵坐标就好了,但与之而来的,就是要 O(1)O(1) 判断交点坐标是否能够 (x,y)(x,y) 移到 (x±1,y)(x\pm1,y) 或者 (x,y±1)(x,y\pm1),这不难,我们只要 n2n^2 预处理出每个点向上,下,左,右最多能有多少个 .*。(写的时候注意查看自己写的数组是否包括当前点本身。)

    本质上,从 (x,y)(x,y)(x±1,y)(x\pm1,y) 和从 (x,y)(x,y)(x,y±1)(x,y\pm1) 是相同的,所以我们就只考虑 (x,y)(x,y)(x±1,y)(x\pm1,y) 该如何判断。

    而移动方式无非就是让横向部分左右移,直到能直接移到下(上)一行上,所以我们只要判断 xxx±1x\pm1 两行是否可以移动横向部分的就可以了。

    min(l[x][y],l[xx][y])+min(r[x][y],r[xx][y])>K

    (x,y)(x,y)(x,y±1)(x,y\pm1) 的方式以此类推,判断 yyy±1y\pm1 两列是否可以移动纵向部分的就可以了。

    min(u[x][y],u[x][yy])+min(d[x][y],d[x][yy])>L

    于是我们就做完了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    // #pragma GCC optimize(2)
    // #pragma GCC optimize(3)
    // #define gc getchar
    #define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #define FILE(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
    #define FIN(s) freopen(s".in","r",stdin);
    #define FOUT(s) freopen(s".out","w",stdout);
    #define ll long long
    #define pll pair<ll,ll>
    #define re register int
    #define rl register ll
    #define il inline
    #define yes putchar('Y'),putchar('E'),putchar('S'),putchar('\n')
    #define no putchar('N'),putchar('O'),putchar('\n')
    using namespace std;
    const int MN=1.5e3+5;
    ll n,m,K,L,xh,yh,xv,yv,l[MN][MN],r[MN][MN],u[MN][MN],d[MN][MN],dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    bool vis[MN][MN];
    char buf[1<<23],*p1=buf,*p2=buf,mp[MN][MN];
    queue<pll> q;
    il void write(rl n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
    il ll read(){ll x=0,f=1;char ch=gc();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}return x*f;}
    il char getc(){char ch=gc();while(ch!='.'&&ch!='*'&&ch!='X')ch=gc();return ch;}
    int main(){
        // ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        m=read();n=read();K=read();L=read();yh=read()+1;xh=read()+1;yv=read()+1;xv=read()+1;
        for(re i=1; i<=n; ++i) for(re j=1; j<=m; ++j) mp[i][j]=getc();
        for(re i=1; i<=n; ++i) for(re j=1; j<=m; ++j) if(mp[i][j]!='X') l[i][j]=l[i][j-1]+1,u[i][j]=u[i-1][j]+1;
        for(re i=n; i; --i) for(re j=m; j; --j) if(mp[i][j]!='X') r[i][j]=r[i][j+1]+1,d[i][j]=d[i+1][j]+1;
        q.push({xh,yv});while(!q.empty()){
            ll x=q.front().first,y=q.front().second;q.pop();
            if(mp[x][y]=='*'){yes;return 0;}
            if(vis[x][y]) continue;vis[x][y]=true;
            for(re i=0; i<4; ++i){
                ll xx=x+dx[i],yy=y+dy[i];
                if(mp[xx][yy]=='X') continue;
                if(dx[i]&&min(l[x][y],l[xx][y])+min(r[x][y],r[xx][y])>K) q.push({xx,y});
                if(dy[i]&&min(u[x][y],u[x][yy])+min(d[x][y],d[x][yy])>L) q.push({x,yy});
            }
        }no;
        return 0;
    }//250818
    
    • 1

    信息

    ID
    10575
    时间
    1350ms
    内存
    1024MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者