您的位置:首页 > 其它

[BZOJ2541][Ctsc2000]冰原探险(bfs)

2016-10-30 13:46 417 查看

题目描述

传送门

题解

乍一看这道题好像无从下手,实际上就是预处理之后bfs。

因为要冰块要撞上冰山了之后才能停下来,所以从一个地方向某一个方向推它停在哪里是一定的,并且从某一个冰山左右只能忘上下推,从一个冰山的上下只能往左右推。那这样的话,就可以把每一个冰山的四边编上号,然后每一次暴力查找往某个方向推会撞到哪里。将这两个部分连边。那这样的话就会出来一个有向图,用一遍bfs就可以求出最短路。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define N 100005
#define LL long long

const LL inf=1e18;
int n,cnt,ans;
LL A,B,C,D;
int tot,point
,nxt[N*2],v[N*2];
bool vis
;
struct hp{LL a,b,c,d;int p[10];}s[4005];
struct hq{int x,step;};
queue <hq> q;

int find_up(LL x,LL y)
{
int ans=0;LL Max=-inf;
for (int i=1;i<=n;++i)
{
LL a=s[i].a,b=s[i].b,c=s[i].c,d=s[i].d;
if (c+1<=x&&y>=b&&y<=d&&Max<c+1)
{
Max=c+1;
ans=s[i].p[2];
}
}
if (y==D&&C<=x&&Max<C) ans=cnt;
return ans;
}
int find_down(LL x,LL y)
{
int ans=0;LL Min=inf;
for (int i=1;i<=n;++i)
{
LL a=s[i].a,b=s[i].b,c=s[i].c,d=s[i].d;
if (a-1>=x&&y>=b&&y<=d&&Min>a-1)
{
Min=a-1;
ans=s[i].p[1];
}
}
if (y==D&&x<=C&&Min>C) ans=cnt;
return ans;
}
int find_left(LL x,LL y)
{
int ans=0;LL Max=-inf;
for (int i=1;i<=n;++i)
{
LL a=s[i].a,b=s[i].b,c=s[i].c,d=s[i].d;
if (d+1<=y&&x>=a&&x<=c&&Max<d+1)
{
Max=d+1;
ans=s[i].p[4];
}
}
if (x==C&&D<=y&&Max<D) ans=cnt;
return ans;
}
int find_right(LL x,LL y)
{
int ans=0;LL Min=inf;
for (int i=1;i<=n;++i)
{
LL a=s[i].a,b=s[i].b,c=s[i].c,d=s[i].d;
if (b-1>=y&&x>=a&&x<=c&&Min>b-1)
{
Min=b-1;
ans=s[i].p[3];
}
}
if (x==C&&D>=y&&Min>D) ans=cnt;
return ans;
}
void add(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
int bfs()
{
memset(vis,0,sizeof(vis));vis[1]=true;
while (!q.empty()) q.pop(); q.push((hq){1,0});
while (!q.empty())
{
hq now=q.front();q.pop();
for (int i=point[now.x];i;i=nxt[i])
{
if (v[i]==cnt) return now.step+1;
if (!vis[v[i]])
{
vis[v[i]]=true;
q.push((hq){v[i],now.step+1});
}
}
}
return 0;
}
int main()
{
scanf("%d",&n);
scanf("%lld%lld%lld%lld",&A,&B,&C,&D);
for (int i=1;i<=n;++i) scanf("%lld%lld%lld%lld",&s[i].a,&s[i].b,&s[i].c,&s[i].d);
cnt=1;
for (int i=1;i<=n;++i)
for (int j=1;j<=4;++j) s[i].p[j]=++cnt;
++cnt;int x;
x=find_up(A,B); if (x) add(1,x);
x=find_down(A,B); if (x) add(1,x);
x=find_left(A,B); if (x) add(1,x);
x=find_right(A,B); if (x) add(1,x);
for (int i=1;i<=n;++i)
{
LL a=s[i].a,b=s[i].b,c=s[i].c,d=s[i].d;
int x;
x=find_up(a,b-1); if (x) add(s[i].p[3],x);
x=find_up(a,d+1); if (x) add(s[i].p[4],x);
x=find_down(c,b-1); if (x) add(s[i].p[3],x);
x=find_down(c,d+1); if (x) add(s[i].p[4],x);
x=find_left(a-1,b); if (x) add(s[i].p[1],x);
x=find_left(c+1,b); if (x) add(s[i].p[2],x);
x=find_right(a-1,d); if (x) add(s[i].p[1],x);
x=find_right(c+1,d); if (x) add(s[i].p[2],x);
}
ans=bfs();
printf("%d\n",ans);
}


总结

①码力太弱了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: