题目不难,大致题意为:
给定一个迷宫,给定迷宫的状态,即迷宫的每条单位边可能是wall,也可能是door,也可能是空。这些状态以点加方向加长度的形式给出。并给定搜索的起点和终点。要求出从起点到终点所必须经过的最少door数量。简单的搜索题。
主要是题目中迷宫的状态转化为常规的二维矩阵比较伤脑筋,也比较麻烦,其余的都好解决。
这里转化思路如下:
边分为横向和纵向两种方向,分别用0和1表示。可以事先创建一个三维矩阵pos[i][j][0]表示坐标(i,j)点横向一个单位的迷宫状态,用pos[i][j][1]表示坐标(i,j)点纵向一个单位的迷宫状态。用-1、0、1分别表示是空、door和wall。由于输入中只是输入door和wall的情况,所以可以事先将pos数字设为-1即均为空状态。然后根据输入依次填充pos数组。同时在输入的过程中将迷宫左下点(lowx,lowy)和右上点(topx,topy)的坐标求出来(通过比较,这个容易实现)。接着就进入转化了。转化过程如下:
事先设置四个二维数组,分别为tran_left、tran_right、tran_top、tran_low。设h=topy-lowy+2,w=topx-lowx。转化后的方格为h*w规格(不难想象)。用tran_left数组表示相邻点从左边一个方格到右边一个方格中间的边是wall、door、还是空。依次类推:right、top、low分别表示从右边到左边、从下到上、从上到下中间的边是wall、door、还是空。这个转化通过pos数组进行(不难实现),转化结束。
这里要注意几个问题:
1)由于终点可能并不再迷宫内,故要实现判定终点是否在迷宫内部,如果不再则输出0,否则根据转化后的矩阵dfs或bfs搜索最少值即可
2)根据dfs或bfs搜索最小值,若无法到大终点,则要输出-1,否则输出最小值
3)转化后的矩阵搜索起点应该在终点比较合适(已判定在迷宫内)
下面是代码: 1540K+47MS
#include
#include
#include
#define Max 210
#define Inf 10000010 //无穷大
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}}; //四个搜索方向,上、下、左、右
int tran_top[Max][Max];
int tran_low[Max][Max];
int tran_left[Max][Max];
int tran_right[Max][Max];
int pos[Max][Max][2];
bool flag[Max][Max]; //记录格点是否搜索
int lowx,lowy,topx,topy; // 迷宫坐下点(lowx,lowy) 右下点(topx,topy)
int tx,ty; //转化后的终点坐标
int Sum; //最终结果
int n,m;
int h,w; //转化后的方格规格
int get_tran(int x,int y,int index){ // 得到从点(x,y)分别向上、下、左、右方向时遇到的是wall、door还是空
if(index==0)
return tran_top[x][y];
else if(index==1)
return tran_low[x][y];
else if(index==2)
return tran_left[x][y];
else
return tran_right[x][y];
}
void dfs(int x,int y,int num){ // dfs搜索最小值
if(num>=Sum) // 剪枝,若大于最小值,则直接返回
return ;
if(x==1 || x==h || y==1 || y==w){ //终点判定,若能到达迷宫外,说明可以找到,逆向搜索
Sum=num;
return ;
}
for(int i=0;i<4;i++){ //分别搜索四个方向
int tempx=x+dir[i][0],tempy=y+dir[i][1];
if(get_tran(x,y,i)==0 && !flag[tempx][tempy]){ //若为door,并且下一步方格没有搜索,则往该方向继续搜索
flag[tempx][tempy]=true;//设置为已经搜索
dfs(tempx,tempy,num+1);//继续深搜
flag[tempx][tempy]=false;//回溯
}
else if(get_tran(x,y,i)==-1 && !flag[tempx][tempy]){//若为空,则同上
flag[tempx][tempy]=true;
dfs(tempx,tempy,num);
flag[tempx][tempy]=false;
}
}
}
int main(){
while(scanf("%d%d",&n,&m),n!=-1){
int i,j,tex,tey,ted,tet;
memset(pos,-1,sizeof(pos)); //初始化为-1
lowx=lowy=Inf; // 初始化左下点坐标,右上点坐标
topx=topy=-1;
for(i=1;i<=n;i++){
scanf("%d%d%d%d",&tex,&tey,&ted,&tet);
if(textopx) topx=tex+tet; //右上点坐标
if(tey>topy) topy=tey;
for(j=tex;jtopx) topx=tex;
if(tey+tet>topy) topy=tey+tet;
for(j=tey;jtopx) topx=tex+1;
if(tey>topy) topy=tey;
pos[tex][tey][0]=0; //设置横向pos
}
else{
if(tex>topx) topx=tex;
if(tey+1>topy) topy=tey+1;
pos[tex][tey][1]=0; // 设置纵向pos
}
}
int ix,iy;
for(i=lowy;i
tran_right[ix+1][iy-1]=tran_left[ix+1][iy]=pos[j][i][1];
}
}
h=topy-lowy+2,w=topx-lowx+2; //方格规模
for(i=lowx;i=topx || tempy<=lowy || tempy>=topy){ //判断点是否在迷宫内
printf("0\n");
continue;
}
tx=int(tempy-lowy)+2;
ty=int(tempx-lowx)+2;
memset(flag,0,sizeof(flag));
flag[tx][ty]=1;
Sum=Inf;
dfs(tx,ty,0);
if(Sum==Inf) //若达不到终点
printf("-1\n");//输出-1
else //否则输出最小值
printf("%d\n",Sum);
}
return 0;
}