[睡梦前的灵感]仓库路线设计

【描述】

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;
}

 

posted @ 2010-09-21 17:24  Sephiroth.L.  阅读(297)  评论(0编辑  收藏  举报