您的位置:首页 > 其它

bzoj 3161: 孤舟蓑笠翁 bfs

2016-04-07 15:15 162 查看
显然,可以把左手在i点,右手在j点缩成一个状态(想到这个就基本结束了),那么去掉不合法的状态之后,可以根据停顿点的移动条件得到一个状态可以转移到那些状态。这就相当于一个图,而边权都是1,然后要求的就是离一个特殊点最近的特殊点。

注意是平面图,因此用bfs得到一个点离它最近的特殊点以及距离,将这个点加入该特殊点的“势力范围”,那么对于一对特殊点(u,v),v是离u最近的特殊点当且当u和v的“势力范围”有接壤。然后直接用边界上面的边更新一下答案即可。

注意状态和状态之间的边的数量看起来很大,但是实际上也只有O((N+M)^2),由于题目中的坐标的两维相互独立,因此不需要直接在状态直接连边。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#define N 1005
#define M 20005
#define inf 1000000000
using namespace std;

int n,m,tot,cnt,d

,blg

,pnt[M],nxt[M],ans[N*N]; bool bo

;
struct node{ int x,y; }a
,h[N*N];
int read(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x;
}
struct graph{
int fst
;
void add(int x,int y){
pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
}g1,g2;
int main(){
n=read(); m=read(); int i,j,k,x,y,mn=read(),mx=read();
for (i=1; i<=n; i++){
a[i].x=read(); a[i].y=read();
}
for (i=1; i<=n; i++)
for (j=1; j<=n; j++){
k=abs(a[i].x-a[j].x)+abs(a[i].y-a[j].y);
if (k>=mn && k<=mx) bo[i][j]=1;
}
cnt=read();
for (i=1; i<=cnt; i++){
h[i].x=read(); h[i].y=read();
blg[h[i].x][h[i].y]=i;
}
while (m--){
x=read(); y=read(); k=read();
if (!k){ g1.add(x,y); g1.add(y,x); }
else{ g2.add(x,y); g2.add(y,x); }
}
for (i=1; i<=n; i++){
g1.add(i,i); g2.add(i,i);
}
int head=0,tail=cnt;
while (head<tail){
x=h[++head].x; y=h[head].y;
for (i=g1.fst[x]; i; i=nxt[i])
for (j=g2.fst[y]; j; j=nxt[j]){
node t; t.x=pnt[i]; t.y=pnt[j];
if (!blg[t.x][t.y] && bo[t.x][t.y]){
d[t.x][t.y]=d[x][y]+1;
blg[t.x][t.y]=blg[x][y]; h[++tail]=t;
}
}
}
memset(ans,0x3f,sizeof(ans));
for (x=1; x<=n; x++)
for (y=1; y<=n; y++) if (blg[x][y])
for (i=g1.fst[x]; i; i=nxt[i])
for (j=g2.fst[y]; j; j=nxt[j]){
int u=pnt[i],v=pnt[j];
if (blg[u][v] && blg[x][y]!=blg[u][v]){
k=d[x][y]+d[u][v]+1;
ans[blg[x][y]]=min(ans[blg[x][y]],k);
ans[blg[u][v]]=min(ans[blg[u][v]],k);
}
}
for (i=1; i<=cnt; i++)
printf("%d\n",(ans[i]<inf)?ans[i]:-1);
return 0;
}


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