题意:有一个BOARD上有很多很多相同大小的卡片。有的位置是空的,有的位置放了卡片。
问卡片a和卡片b能不能用横纵直线段连起来,如果能求连线最少由多少段组成,连线
可以暂时离开BOARD。
思路:
1、刚开始看真的很像连连看,但是连连看只能转两次。这个允许转多次。只是要尽可能少转弯。
怎么保证少转弯呢,尽可能总是沿着当前方向走,直到走不了了再转换方向。
2、尽可能沿着同一方向走,那么BFS搜的时候,没转方向的那条线上的步数是一样的。每次都在当前
节点的坐标上修改移动后的坐标,但是步数在这条线段的第一个节点基础上+1。
3、还要注意每组数据搜的时候把起点和终点改为' ',不然搜不到。结束的时候也要改回来,为下一次搜索
保留现场。
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
struct node
{
int x,y;
}s;
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
char map[80][80];
int step[80][80];
int n,m,x1,y1,x2,y2;
bool ok(int x,int y)
{
if(x>=0 && x<=n+1 && y>=0 && y<=m+1)
return true;
return false;
}
int bfs(int x1,int y1,int x2,int y2)
{
queue<node> q;
s.x = x1;
s.y = y1;
step[s.x][s.y] = 0;
map[x1][y1] = ' ';
map[x2][y2] = ' ';
q.push(s);
node cur,next,u;
while(!q.empty())
{
u = q.front();
//cout<<step[u.x][u.y]<<endl;
q.pop();
if(u.x == x2 && u.y == y2)
return step[x2][y2];
for(int i=0;i<4;i++)
{
cur = u;
next.x = cur.x+dx[i];
next.y = cur.y+dy[i];
while(ok(next.x,next.y) && map[next.x][next.y]==' ' && step[next.x][next.y]==-1)
{
step[next.x][next.y] = step[u.x][u.y]+1; //在u的步数基础上+1,而不是当前节点
q.push(next);
cur = next;
next.x = cur.x+dx[i];
next.y = cur.y+dy[i];
}
}
}
return -1;
}
int main()
{
int cas=1;
while(scanf("%d%d",&m,&n)!=EOF) //n行m列
{
if(m==0 && n==0)
break;
getchar();
for(int i=1;i<=n;i++)
gets(map[i]+1);
for(int i=0;i<=m+1;i++)
{
map[0][i]=' ';
map[n+1][i]=' ';
}
for(int j=0;j<=n+1;j++)
{
map[j][0]=' ';
map[j][m+1]=' ';
}
int tes=1;
printf("Board #%d:\n",cas++);
while(1)
{
scanf("%d%d%d%d",&y1,&x1,&y2,&x2);
if(x1==0 && y1==0 && x2==0 && y2==0)
{
//cas++;
break;
}
memset(step,-1,sizeof(step));
printf("Pair %d: ",tes);
int ans = bfs(x1,y1,x2,y2);
if(ans == -1)
printf("impossible.\n");
else
printf("%d segments.\n",ans);
tes++;
map[x1][y1] = map[x2][y2] ='X';
}
printf("\n");
}
return 0;
}