推箱子

  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 }

 

 

 posted on 2014-04-01 09:30  莫扎特的代码  阅读(256)  评论(0编辑  收藏  举报