JZOJ5381. 【NOIP2017提高A组模拟9.21】传送蛋糕
程序员文章站
2024-02-12 22:46:10
...
题解
这里面的传送门是比较特殊的,
我们可以发现,传送门的实质就是:
在某个点(x,y)到它四周的墙的距离都为它到四面墙的最短距离。
那么我们就可以连边,
每个点向外连8条边。
然而,边数是十分巨大的,并不能全部记录下来。
我们可以O(nm)预处理出来每个点,往四周走,
碰到的第一面墙,利用这个可以快速地求出这个点向外连的8条边。
还有一个优化,就是在spfa中的队列,
要从dis小的开始枚举,这样每个点的进队次数就不会超过8。
code
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 2333
#define db double
#define P putchar
#define G getchar
#define mo 1004535809
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void write(int x)
{
if(x>9) write(x/10);
P(x%10+'0');
}
struct node
{
int x,dis;
}t,now;
bool operator <(node a,node b)
{
return a.dis>b.dis;
}
priority_queue <node> q;
int f[N][N][4],n,m,dis[N*N],stx,sty,fix,fiy,mi,p,x,y,to,v;
//int nxt[N*N*8],to[N*N*8],v[N*N*8],b[N*N],tot;
bool bz[N*N];
char a[N][N];
int get(int x,int y)
{
return x*(m+2)+y;
}
//void ins(int x,int y,int z){nxt[++tot]=b[x];to[tot]=y;v[tot]=z;b[x]=tot;}
int main()
{
freopen("portals.in","r",stdin);
freopen("portals.out","w",stdout);
read(n);read(m);ch='-';
for(int i=1;i<=n;i++)
{
a[i][0]=a[i][m+1]='#';
while(ch!='S' && ch!='.' && ch!='#' && ch!='C')ch=getchar();
for(int j=1;j<=m;j++)
{
if(ch=='S')stx=i,sty=j;
if(ch=='C')fix=i,fiy=j;
a[i][j]=ch,ch=getchar();
}
}
for(int i=0;i<=m+1;i++)
a[0][i]=a[n+1][i]='#';
for(int i=0;i<=n+1;i++)
for(int j=0;j<=m+1;j++)
if(a[i][j]!='#')
f[i][j][0]=f[i-1][j][0]+1,f[i][j][3]=f[i][j-1][3]+1;
for(int i=n+1;i>=0;i--)
for(int j=m+1;j>=0;j--)
if(a[i][j]!='#')
f[i][j][2]=f[i+1][j][2]+1,f[i][j][1]=f[i][j+1][1]+1;
/*for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i][j]=='#')continue;
p=get(i,j);
ins(p,get(i+1,j),1);
ins(p,get(i-1,j),1);
ins(p,get(i,j+1),1);
ins(p,get(i,j-1),1);
mi=min(min(f[i][j][0],f[i][j][1]),min(f[i][j][2],f[i][j][3]));
ins(p,get(i-f[i][j][0]+1,j),mi);
ins(p,get(i+f[i][j][2]-1,j),mi);
ins(p,get(i,j+f[i][j][1]-1),mi);
ins(p,get(i,j-f[i][j][3]+1),mi);
}*/
/*for(int i=0;i<=n+1;i++)
{
for(int j=0;j<=m+1;j++)
{
write(f[i][j][0]),P(' ');
write(f[i][j][1]),P(' ');
write(f[i][j][2]),P(' ');
write(f[i][j][3]),P('\n');
write(min(min(f[i][j][0],f[i][j][1]),min(f[i][j][2],f[i][j][3]))),P(' ');
}
P('\n');
}*/
memset(dis,127,sizeof(dis));
memset(bz,0,sizeof(bz));
dis[t.x=get(stx,sty)]=0;
t.dis=0;bz[t.x]=1;
q.push(t);
while(!q.empty())
{
now=q.top();q.pop();
p=now.x;
x=p/(m+2);y=p%(m+2);
//write(now.dis),P('\n');
//write(x),P(' '),write(y),P('\n');
if(a[x][y]=='#')continue;
v=1;
to=get(x+1,y);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
to=get(x-1,y);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
to=get(x,y+1);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
to=get(x,y-1);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
v=min(min(f[x][y][0],f[x][y][1]),min(f[x][y][2],f[x][y][3]));
to=get(x-f[x][y][0]+1,y);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
to=get(x+f[x][y][2]-1,y);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
to=get(x,y+f[x][y][1]-1);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
to=get(x,y-f[x][y][3]+1);
if(dis[to]>dis[p]+v){dis[to]=dis[p]+v;if(!bz[to]){bz[to]=1;t.x=to;t.dis=dis[to];q.push(t);}}
/*
for(int i=b[p];i;i=next[i])
if(dis[to[i]]>dis[p]+v[i])
{
dis[to[i]]=dis[p]+v[i];
if(!bz[to[i]])
{
bz[to[i]]=1;
t.x=to[i];t.dis=dis[to[i]];
q.push(t);
}
}*/
bz[p]=0;
}
write(dis[get(fix,fiy)]);
}