您的位置:首页 > 其它

1254 推箱子

2016-07-20 23:33 387 查看
(c语言版)整体思路:主线是以箱子为中心做广搜,能不能扩展某个点的条件是人能不能到到达(箱子要去方向的反方向这点)这时再写一个广搜(搜人能否到达这点),(人的位置总是在箱子移动前的位置可以找到不熟的话做hdu 1026打印路径的题)(要扩展的目标终点也有,可以写)整理代码的严谨性和逻辑性就完成了。

#include<cstdio>
#include<cstring>
using namespace std;
const int N=10;
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int book

;
struct f{
int x,y,step;
int early;
}b[4*N*N],c[4*N*N];
int a

;
int bookx

;
int n,m,peox,peoy,bx,by;
int jud(int px,int py){//people+box
int head=0,tail=1;
c[head].x=peox,c[head].y=peoy;
if(peox==px&&peoy==py) return 1;//如果人的初始位置满足条件就不需要扩展点了(开始忘了这个细节)
memset(bookx,0,sizeof(bookx));
while(head<tail){
for(int i=0;i<4;i++)
{
int tx=c[head].x+next[i][0],ty=c[head].y+next[i][1];
if(tx<1||tx>n||ty<1||ty>m||a[tx][ty]==1||bookx[tx][ty]) continue;
if(tx==bx&&ty==by) continue;
bookx[tx][ty]=1;
c[tail].x=tx,c[tail++].y=ty;
if(tx==px&&ty==py) {return 1;}
}
head++;
}
return 0;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int startx,starty,endx,endy;
scanf("%d%d",&n,&m);//输错行列
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]==2){startx=i,starty=j;}
if(a[i][j]==3){endx=i,endy=j;}
if(a[i][j]==4){peox=i,peoy=j;}
}
int head=0,tail=1,flag=0;
b[head].x=startx,b[head].y=starty,b[head].step=0,b[head].early=0;
memset(book,0,sizeof(book));
while(head<tail){
bx=b[head].x,by=b[head].y;//箱子位置
if(head){peox=b[b[head].early].x,peoy=b[b[head].early].y;}//人的位置(为箱子上个的位置)
for(int i=0;i<4;i++)
{
int tx=bx+next[i][0],ty=by+next[i][1];
int px=bx-next[i][0],py=by-next[i][1];
if(tx<1||tx>n||ty<1||ty>m||a[tx][ty]==1) continue;
if(px<1||px>n||py<1||py>m) continue;
if(!book[bx][by][tx][ty]&&jud(px,py)){//四维标记(人的位置(即当前箱子的位置)加箱子的位置)
book[bx][by][tx][ty]=1;
b[tail].x=tx,b[tail].y=ty,b[tail].step=b[head].step+1,b[tail++].early=head;
if(tx==endx&&ty==endy){
flag=1;break;
}
}
}
if(flag) break;
head++;
}
if(flag) printf("%d\n",b[tail-1].step);
else printf("-1\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  广搜嵌套C版