天天寫演算法之push box
阿新 • • 發佈:2019-01-30
這個題的痛點在於思路問題,而且如何標記已經走過的路線,這裡的標記是標記人與三個箱子之間的相對位置,並不是說,你走過了以後,就不能再走了,只要其中一個箱子的位置發生了變化,那麼就可以繼續走。
程式碼是模的。也拓寬一下自己的思路。BFS用的還不是得心應手
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define inf 0x3f3f3f3f using namespace std; bool Hash[8][8][8][8][8][8][8][8]; char map[8][8]; int n,m,ans; int dir[4][2]={{0,1,},{0,-1},{1,0},{-1,0}}; struct node { int x,y; }; struct state { node h,box[3]; int st; bool isok() { if(h.x>=0&&h.x<n&&h.y>=0&&h.y<m&&map[h.x][h.y]!='#') return true; return false; } }a,b; void sethash(state cur)//記錄狀態 { Hash[cur.h.x][cur.h.y][cur.box[0].x][cur.box[0].y][cur.box[1].x][cur.box[1].y][cur.box[2].x][cur.box[2].y]=true; } bool gethash(state cur)//判斷當前狀態是否走過 { return Hash[cur.h.x][cur.h.y][cur.box[0].x][cur.box[0].y][cur.box[1].x][cur.box[1].y][cur.box[2].x][cur.box[2].y]; } bool find(state cur)// 判斷箱子是不是都推到洞裡去了 { int i; for(i=0;i<3;++i){ if(map[cur.box[i].x][cur.box[i].y]!='@') break; } if(i!=3) return false; return true; } int isbox(state cur)//判斷這個位置是不是箱子,如果是,返回箱子的序號 { for(int i=0;i<3;++i){ if(cur.h.x==cur.box[i].x&&cur.h.y==cur.box[i].y) return i; } return -1; } bool logic(state cur,int d,int cnt)//判斷同方向上的下一個點,如果位置越界,或者是牆或箱子,返回false; { state next; next.h.x=cur.h.x+dir[d][0]; next.h.y=cur.h.y+dir[d][1]; if(!next.isok()) return false; for(int i=0;i<3;++i){ if(next.h.x==cur.box[i].x&&next.h.y==cur.box[i].y&&i!=cnt) return false; } return true;//可以推箱子 } int bfs() { queue<state> q; a.st=0; q.push(a); while(!q.empty()){ a=q.front(),q.pop(); if(find(a)){ return ans=a.st; } for(int i=0;i<4;++i){ b=a; b.h.x=a.h.x+dir[i][0]; b.h.y=a.h.y+dir[i][1]; b.st=a.st+1; if(!b.isok()) continue; //位置不合法 int which=isbox(b); if(which!=-1){//如果 這個位置是箱子 if(logic(b,i,which)){ //同方向上的下個位置是路,把箱子推過去,改變它的座標 b.box[which].x=b.h.x+dir[i][0]; b.box[which].y=b.h.y+dir[i][1]; if(!gethash(b)){//當前狀態沒有記錄過 sethash(b);//記錄狀態 q.push(b);//入隊 } } } else{//當前位置是路或者是洞,直接走 if(!gethash(b)){ sethash(b); q.push(b); } } } } return -1; } int main() { //freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); while(scanf("%d%d",&n,&m)!=EOF){ getchar(); int cnt=0; for(int i=0;i<n;++i){ for(int j=0;j<m;++j){ map[i][j]=getchar(); if(map[i][j]=='X'){ a.h.x=i,a.h.y=j; } if(map[i][j]=='*'){ a.box[cnt].x=i,a.box[cnt++].y=j;//記錄每個箱子的座標 } } getchar(); } memset(Hash,false,sizeof Hash); sethash(a); printf("%d\n",bfs()); } return 0; }