bzoj 3161: 孤舟蓑笠翁 bfs
2016-04-07 15:15
162 查看
显然,可以把左手在i点,右手在j点缩成一个状态(想到这个就基本结束了),那么去掉不合法的状态之后,可以根据停顿点的移动条件得到一个状态可以转移到那些状态。这就相当于一个图,而边权都是1,然后要求的就是离一个特殊点最近的特殊点。
注意是平面图,因此用bfs得到一个点离它最近的特殊点以及距离,将这个点加入该特殊点的“势力范围”,那么对于一对特殊点(u,v),v是离u最近的特殊点当且当u和v的“势力范围”有接壤。然后直接用边界上面的边更新一下答案即可。
注意状态和状态之间的边的数量看起来很大,但是实际上也只有O((N+M)^2),由于题目中的坐标的两维相互独立,因此不需要直接在状态直接连边。
AC代码如下:
by lych
2016.4.7
注意是平面图,因此用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
相关文章推荐
- Ehcache(02)——ehcache.xml简介
- Hibernate 多对多双向关联
- 指针数组,指针指向const成员函数
- Linux下安装Monogodb-3.2.4
- 十六进制字符串转化成字符串输出HexToStr(Delphi版、C#版)
- 执行session.createSQLQuery(querySql).list()多次后,再次执行没有动静
- 从一个简单的实例来了解PE文件
- Oracle数据库 Null值 总结
- 剑指offer:二叉树的下一个结点
- 【程序猿人生】关爱程序猿 从此刻开始!
- System.load 和 System.loadLibrary详解
- adb工具使用
- Ehcache项目启动时报Update check failed异常的解决方法
- Delphi 实现16进制转字符串及字符串(中文)转16进制
- 理解 Javascript 的闭包
- 3、Object对象的两大方法(hashCode-equals)总结
- Android高级控件----AdapterView与Adapter
- 平台调用之如何利用VS2013 C#调试C++DLL库
- 样式设置
- 深入理解java虚拟机--第七章类加载