69.广搜练习:  最少转弯问题(TURN)


【问题描述】

        给出一张地图,这张地图被分为n×mn,m<=100)个方块,任何一个方块不是平地就是高山。平地可以通过,高山则不能。现在你处在地图的(x1,y1)这块平地,问:你至少需要拐几个弯才能到达目的地(x2,y2)?你只能沿着水平和垂直方向的平地上行进,拐弯次数就等于行进方向的改变(从水平到垂直或从垂直到水平)的次数。例如:如图,最少的拐弯次数为5

 

 

69.广搜练习: <wbr> <wbr>最少转弯问题(TURN)

【输入格式】

1行:  m

2n+1行:整个地图地形描述(0:空地;1:高山),

如(图)第2行地形描述为:1 0 0 0 0 1 0

               3行地形描述为:0 0 1 0 1 0 0

               ……

n+2行:x1  y1  x2  y2  (分别为起点、终点坐标)

【输出格式】

s (即最少的拐弯次数)

【输入输出样例】(见图):

TURN.IN

TURN.OUT

5 7

1 0 0 0 0 1 0

0 0 1 0 1 0 0

0 0 0 0 1 0 1

0 1 1 0 0 0 0

0 0 0 0 1 1 0

1 3 1 7

5

基本思路:利用广搜寻找一条从起点到终点最短路径,利用pre[]数组一直

错误代码:(最先找到的最短路径不一定是拐弯最少的):

#include

#include

using namespace std;

#include

struct Poi{

       int x,y;

};

Poi dl[10001];

int xq,yq,xz,yz,n,m,jz[101][101],pre[101*101],t=0;

int xx[]={0,0,1,-1};

int yy[]={1,-1,0,0};

long long sum=0;

int head=0,tail=1;

void BFS()

{

       dl[tail].x=xq;

       dl[tail].y=yq;

       pre[tail]=0;

       jz[xq][yq]=1;

       while(head

       {

              ++head;

              int x0=dl[head].x,y0=dl[head].y;

              for(int i=0;i<4;++i)

           {

                  int x1=x0+xx[i],y1=y0+yy[i];

                  if(x1>=1&&x1<=n&&y1>=1&&y1<=m&&!jz[x1][y1])

                  {

                         jz[x1][y1]=1;

                         ++tail;

                         dl[tail].x=x1;

                         dl[tail].y=y1;

                         pre[tail]=head;

                     }

                     if(dl[tail].x==xz&&dl[tail].y==yz)

                     {

                            head=tail;

                            break;

                     }

              }

       }

}

void count()

{

       for(int i=tail;pre[pre[i]]!=0;i=pre[i])

       {

              if(dl[i].x!=dl[pre[pre[i]]].x&&dl[i].y!=dl[pre[pre[i]]].y)

              sum++;

       }

}

void input()

{

       scanf("%d%d",&n,&m);

       for(int i=1;i<=n;++i)

         for(int j=1;j<=m;++j)

         scanf("%d",&jz[i][j]);

       scanf("%d%d%d%d",&xq,&yq,&xz,&yz);

   

}

int main()

{

       input();

       BFS();

       count();

       printf("%d",sum);

       return 0;

}

特例:

5 7

0 0 0 1 0 0 0

0 1 0 0 0 1 0

0 0 1 1 1 0 0

0 1 0 0 0 0 0

0 0 0 0 0 0 0

1 1 1 7

正确答案:是2错误答案:4(是找到最短路)

正确代码:

 

#include

#include

using namespace std;

#include

const int INF=999999;

int n,m,jz[101][101];

struct Dl{

       int x,y;

};

Dl dl[101*101];

int xq,xz,yz,yq,turn[101][101],x0,y0;int k;int head=0,tail=1;

void input()

{

       scanf("%d%d",&n,&m);

       for(int i=1;i<=n;++i)

         for(int j=1;j<=m;++j)

         scanf("%d",&jz[i][j]);

         scanf("%d%d%d%d",&xq,&yq,&xz,&yz);

       memset(turn,99,sizeof(turn));

}

void search(int i,int j,int p)

{

       k+=p;

       if(turn[i][j]<1667457891) return;//说明之前已经找过了

       ++tail;dl[tail].x=i;

       dl[tail].y=j;

       turn[i][j]=turn[x0][y0]+1;//再找到下个点时,一定已经拐弯了

}

void BFS()

{

       dl[tail].x=xq;

       dl[tail].y=yq;

       turn[xq][yq]=-1;//把初值设为-1,才把与起点共线的步数设为0

       while(head

       {

              ++head;

              x0=dl[head].x,y0=dl[head].y;

              k=x0+1;while(k<=n&&jz[k][y0]==0) search(k,y0,1);//只要是在一条直线上的就一次走到底,拐弯数最少

              k=x0-1;while(k>=1&&jz[k][y0]==0) search(k,y0,-1);

              k=y0+1;while(k<=m&&jz[x0][k]==0) search(x0,k,1);

              k=y0-1;while(k>=1&&jz[x0][k]==0) search(x0,k,-1);

             

       }

}

int main()

{

       input();

       BFS();

    printf("%d",turn[xz][yz]);

       return 0;

}

//1667457891

原文地址:https://www.cnblogs.com/c1299401227/p/5370770.html