推箱子
1 /************************************************************** 2 作者:陈新 3 邮箱:cx2pirate@gmail.com 4 用途:hdu1254_2 5 时间ﺿ014.3.31 21:11 6 测试ﺿ0447364 2014-04-01 08:51:18 Accepted 1254 15MS 296K 3724 B G++ 超级旅行者 7 *************************************************************/ 8 9 #include <cstdio> 10 #include <memory.h> 11 #include <queue> 12 #include <map> 13 14 using namespace std; 15 16 #define MAPSIZE 7 17 #define FLOOR 0 18 #define WALL 1 19 #define BOX 2 20 #define DESTINATION 3 21 #define WORKER 4 22 23 //坐标 24 typedef struct COOR{ 25 int x,y; 26 bool operator ==(const COOR &rhs) const{ 27 return x == rhs.x && y == rhs.y; 28 } 29 bool operator !=(const COOR &rhs) const{ 30 return x != rhs.x || y != rhs.y; 31 } 32 bool operator <(const COOR &rhs) const{ 33 return x < rhs.x || (x == rhs.x && y < rhs.y); 34 } 35 }COOR; 36 37 //worker,box的位置组成搜索节点 38 //为使用map 对运算法重载 39 typedef struct NODE{ 40 COOR worker; 41 COOR box; 42 int dir; 43 int steps; 44 bool operator <(const NODE &rhs)const{ 45 return worker < rhs.worker || (worker == rhs.worker && box < rhs.box); 46 } 47 }NODE; 48 49 50 int gMap[MAPSIZE][MAPSIZE]; //地图 51 int vis[MAPSIZE][MAPSIZE]; //dfs中使用, 52 int mapX,mapY; //mapX地图高,mapY地图宽 53 bool found; 54 int DIREC[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; 55 int REVER[4] = {1,0,3,2}; //DIREC中反方向对应的索引 56 queue<NODE> unvis; 57 map<NODE,bool> visited; //用map记录已经扩展的节点, 58 59 void initMap(); //初始化地图 60 int findAWay(); //找到推箱子路径,有路径返回最小步骤,否则返回-1 61 void getCoor(COOR *worker,COOR *box,COOR *dest); //从地图中获得worker,box,destination初始坐标 62 COOR move(COOR from,int dir); //移动一个坐标,返回移动后的坐标 63 void addNodes(COOR worker,COOR box,int steps); //把worker移动到box上下左右组成搜索节点,添加到unvis 64 bool reach(COOR worker,COOR box,COOR aroundBox); //返回worker是否能到达box周围的坐标aroundBox 65 void dfs(COOR worker,COOR box,COOR aroundBox); //reach中采用的dfs 66 bool notWall(COOR pos); //坐标在地图内且不是墙返回真,否则返回假 67 68 int main(){ 69 int caseNum; 70 scanf("%d",&caseNum); 71 72 while(caseNum--){ 73 initMap(); 74 int steps = findAWay(); 75 printf("%d\n",steps); 76 } 77 } 78 79 void initMap(){ 80 scanf("%d%d",&mapX,&mapY); 81 for(int i = 0;i < mapX;i++){ 82 for(int j = 0;j < mapY;j++){ 83 scanf("%d",&gMap[i][j]); 84 } 85 } 86 } 87 88 int findAWay(){ 89 COOR worker,box,dest; 90 getCoor(&worker,&box,&dest); 91 visited.clear(); 92 while(!unvis.empty()){ 93 unvis.pop(); 94 } 95 addNodes(worker,box,0); 96 while(!unvis.empty()){ 97 NODE cur = unvis.front(); 98 unvis.pop(); 99 if(cur.box == dest){ 100 return cur.steps; 101 } 102 // printf("worker : %d %d\tbox : %d %d\tsteps : %d\n",cur.worker.x,cur.worker.y,cur.box.x,cur.box.y,cur.steps); 103 COOR bNext = move(cur.box,cur.dir); 104 if(notWall(bNext)){ 105 addNodes(cur.worker,bNext,cur.steps + 1); 106 } 107 } 108 return -1; 109 } 110 111 void addNodes(COOR worker,COOR box,int steps){ 112 for(int dir = 0;dir < 4;dir++){ 113 COOR aroundBox = move(box,dir); 114 if(reach(worker,box,aroundBox)){ 115 NODE node; 116 node.worker = aroundBox; 117 node.box = box; 118 node.steps = steps; 119 node.dir = REVER[dir]; 120 if(!visited[node]){ 121 visited[node] = true; 122 unvis.push(node); 123 } 124 } 125 } 126 } 127 128 COOR move(COOR from,int dir){ 129 COOR dest = from; 130 dest.x += DIREC[dir][0]; 131 dest.y += DIREC[dir][1]; 132 return dest; 133 } 134 135 bool reach(COOR worker,COOR box,COOR aroundBox){ 136 memset(vis,false,sizeof(vis)); 137 found = false; 138 dfs(worker,box,aroundBox); 139 return found; 140 } 141 142 void dfs(COOR worker,COOR box,COOR aroundBox){ 143 if(worker == aroundBox){ 144 found = true; 145 } 146 if(found){ 147 return; 148 } 149 150 for(int dir = 0;dir < 4;dir++){ 151 COOR wNext = move(worker,dir); 152 if(notWall(wNext) && wNext != box && !vis[wNext.x][wNext.y]){ 153 vis[wNext.x][wNext.y] = true; 154 dfs(wNext,box,aroundBox); 155 } 156 } 157 } 158 159 bool notWall(COOR pos){ 160 return pos.x >= 0 && pos.x < mapX && pos.y >= 0 && pos.y < mapY && gMap[pos.x][pos.y] != WALL; 161 } 162 163 void getCoor(COOR *worker,COOR *box,COOR *dest){ 164 for(int i = 0;i < mapX;i++){ 165 for(int j = 0;j < mapY;j++){ 166 if(gMap[i][j] == WORKER){ 167 worker ->x = i; 168 worker ->y = j; 169 } 170 else if(gMap[i][j] == BOX){ 171 box ->x = i; 172 box ->y = j; 173 } 174 else if(gMap[i][j] == DESTINATION){ 175 dest ->x = i; 176 dest ->y = j; 177 } 178 } 179 } 180 }