P10804 题解

P10804 题解

题面

原题传送门

思路

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

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

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

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

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

\((x,y)\)\((x,y\pm1)\) 的方式以此类推,判断 \(y\)\(y\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
posted @ 2025-08-18 23:28  naroto2022  阅读(6)  评论(0)    收藏  举报