[睡梦前的灵感]仓库路线设计
【描述】
ACK 是一家以生产计算机及其外设产品为主的高科技企业。不仅ACK 的产品在国内领先,而且它的仓库设计也独具特色。由于生产的产品多种多样,ACK的仓库是由若干个大小不等、形状各异的子仓库组成,每个仓库有一个入口(也是出口),坐标为(Xi,Yi)。由于有些产品是互相关联的,所以某些仓库的入口之间通过地下通道相联。(0,0)是地下通道的入口处。每次装卸货物时,仓库的运输车都要从(0,0)处进入地下通道,在通道中行驶一段距离后进入到某一子仓库中装卸货物。但是最近运输车出现了一点小毛病,那就是运输车只能右转弯,而不能左转弯。这对运输车在仓库中运输货物并没有什么影响,但是由于地下通道的宽度有限,运输车转弯的角度不能超过180 (180度也不行)。在这种情况下,某些仓库仍然是可到达的,但是有些仓库却是根本不能到达的。
例如在如上图的例子中,如果运输车的行驶路线为O—B—D—E—F—B—A(这条路线保证了运输车不进行左转弯),则可依次到达子仓库B、D、E、F、A,但是无论运输车如何选择其他的路线,子仓库C 都是不能到达的。
作为ACK 的高级工程师,请你编程找出从O点可以到达的所有子仓库。
注意:为保持仓库的清洁,地下通道采用“管道”的形式(除入口和出口以外都是封闭的),所以即使仓库i 和仓库j 相连,仓库k 的坐标为(Xk,Yk)在(Xi,Yi)和(Xj,Yj)的连线上,当运输车在从仓库i 到仓库j 的路线上时仍不能到达仓库k。
【输入格式】
输入数据文件名为line.in 。文件的第一行为一个整数N(n<=200),表示共有N个子仓库。从第二行开始到第(N+1)行每行有两个数Xi,Yi,(-50<=Xi,Yi<=50)表示第i 个仓库的坐标。然后是一个整数M(M<=100) ,表示共有M 条路线。接下来的M 行每行有两个整数P、Q,表示子仓库P 和子仓库Q 有通道相连,在这里通道是双向的,即如果P 可以和Q相连,那么Q 也一定和P 相连。其中仓库的入口(0,0)用0 表示。
【输出格式】
输出文件为line.out。将可能到达的子仓库序号按升序输出到文件中。输入文件中给出的数据保证至少有一个可达子仓库。
【样例输入】
6
0 4
1 2
2 4
2 3
3 2
2 1
8
0 2
1 2
1 4
2 4
3 4
4 5
5 6
2 6
【样例输出】
1 2 4 5 6
【分析】
题目就是一个限定了条件的宽搜。
对于当前处理的点2,设上一个点是1,判断的点是3。可以进行扩展的条件是a×b>0或者a和b是同向共线向量。然后由于一个点可能扩展到多次,但是一个边(有向)只能扩展到一次,利用这个来限制宽搜。原来用的限制方法是一个点搜到一次……晚上躺床上突然就想出来了的说。好神奇。
#include <stdio.h> #define maxn 210 bool v[maxn][maxn]; struct ss { int x,y; } a[maxn]; int que[maxn*maxn]; struct sss { int x1,y1; } b[maxn]; int n,m,p,q,h,t; int bl[maxn][maxn]; int tx,ty,nx,ny,tnode,nnode; bool can[maxn]; bool ok(int x1,int y1,int x2,int y2) { return ((x1*y2-x2*y1>0)||((x1*y2==x2*y1)&&(x1*x2<=0))); } int main() { freopen("line.in","r",stdin); freopen("line.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y); scanf("%d",&m); for (int i=1;i<=m;++i) { scanf("%d%d",&p,&q); bl[q][++bl[q][0]]=p; bl[p][++bl[p][0]]=q; } while (h<=t) { nnode=que[h]; nx=a[nnode].x; ny=a[nnode].y; if (!h) for (int i=1;i<=bl[0][0];++i) { tnode=bl[0][i]; v[0][tnode]=1; can[tnode]=1; que[++t]=tnode; } else for (int i=1;i<=bl[nnode][0];++i) { tnode=bl[nnode][i]; tx=a[tnode].x; ty=a[tnode].y; if (ok(b[h].x1-nx,b[h].y1-ny,tx-nx,ty-ny)) if (!v[nnode][tnode]) { can[tnode]=1; que[++t]=tnode; b[t].x1=nx; b[t].y1=ny; v[nnode][tnode]=1; } } ++h; } for (int i=1;i<=n;++i) if (can[i]) printf("%d ",i); return 0; }