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 }