您的位置:首页 > 其它

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

2016-03-06 19:51 232 查看
【问题描述】

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



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


【输入格式】

第1行:n m

第2至n+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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: