做完8.4当然就顺便看看8.3,这个题的实验要求是求得箱子最少的移动次数,因此难点在箱子的移动方向,以及回溯法让机器人到达能推动箱子的坐标。
--------------------------------------------------------------------------------------------------------------------
以下是代码实现,采用分支限界法实现该实验,广度搜索得到箱子能移动的方向,然后利用回溯法深度遍历地图判断机器人能否让箱子移动。
-----------------------------------------------------------------------------------------------------------------------------
#include<iostream>
using namespace std;
int row, col;
int INI_BX, INI_BY;//开始时箱子坐标
int INI_TX, INI_TY;//终点
int SX, SY;//机器人
struct heapnode {
int length;//距离终点的距离
int level;//移动的步数
int route[100];//route中的值为0,1,2,3,4,其中0为初始化,1-4代表朝着上下左右移动
int x, y;//route[level]箱子的坐标,方便找位置
};
heapnode heap[100];
int heaplength = 0;
int minlevel = 1e9;//最小移动次数
//小顶堆
void Insert(heapnode temp) {
int i = 0;
for (i = heaplength + 1; i > 1; i/=2) {
if (temp.length >= heap[i / 2].length)break;
else heap[i] = heap[i / 2];
}
heap[i] = temp;
heaplength++;
}
void Delete() {
heapnode temp = heap[heaplength];
heap[1] = heap[heaplength];
int i;
heap[heaplength].length = 1e9;
for (i = 2; i < heaplength; i*=2) {
if (heap[i].length > heap[i + 1].length)i++;
if (heap[i].length >= temp.length)break;
heap[i / 2] = heap[i];
}
heap[i / 2] = temp;
heaplength--;
}
//避免出现浮点数,因此不做根号处理
int GetLen(heapnode temp) {
return ((temp.x - INI_TX) * (temp.x - INI_TX) + (temp.y - INI_TY)* (temp.y - INI_TY));
}
int spath[100][100];//机器人走过的路
//判断机器人是否在绕圈
bool Road(int x, int y) {
if (spath[x][y] == 1) return 0;
return 1;
}
//回溯法让机器人移动到该位置
bool dfs(char **map,int x,int y,heapnode temp) {
//可优化,但懒得改了,这个地方是得到一个tmap地图,将map地图中当前的箱子位置视为障碍物'#'
char** tmap = new char* [row];
for (int i = 0; i < row; i++) tmap[i] = new char[col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++)
tmap[i][j] = map[i][j];
}
tmap[temp.x][temp.y] = '#';//将箱子视为路障
bool is = 0;
if (SX == x && SY == y) return true;
else {
//上
if (tmap[SX - 1][SY] != '#' && Road(SX-1,SY) && !is) {
spath[SX][SY]=1;
SX = SX - 1;
is = dfs(map,x,y,temp);
SX = SX + 1;
spath[SX][SY] = 0;
}
//下
if (tmap[SX + 1][SY] != '#' && Road(SX + 1, SY) && !is) {
spath[SX][SY] = 1;
SX = SX + 1;
is = dfs(map, x, y, temp);
SX = SX - 1;
spath[SX][SY] = 0;
}
//左
if (tmap[SX][SY - 1] != '#' && Road(SX, SY - 1) && !is) {
spath[SX][SY] = 1;
SY = SY - 1;
is = dfs(map, x, y, temp);
SY = SY + 1;
spath[SX][SY] = 0;
}
//右
if (tmap[SX][SY + 1] != '#' && Road(SX, SY + 1) && !is) {
spath[SX][SY] = 1;
SY = SY + 1;
is = dfs(map, x, y, temp);
SY = SY - 1;
spath[SX][SY] = 0;
}
}
return is;
}
//判断机器人能否支持该移动
bool Robot(char **map,int x,int y,heapnode temp) {
if (map[x][y] == '#') return false;
else if (dfs(map, x, y, temp)) return true;
return false;
}
void GetAns(char **map) {
heapnode rootnode;
rootnode.level = 0;
rootnode.x = INI_BX;
rootnode.y = INI_BY;
rootnode.length = GetLen(rootnode);
rootnode.route[0] = 0;
Insert(rootnode);
while (heaplength>0) {
heapnode temp = heap[1];
Delete();
if (temp.length == 0) {
if (minlevel > temp.level) minlevel = temp.level;
}
else {
//推箱子往上
if (map[temp.x - 1][temp.y] != '#' && Robot(map, temp.x + 1, temp.y, temp)) {
heapnode node;
node.x = temp.x - 1;
node.y = temp.y;
node.length = GetLen(node);
node.level = temp.level + 1;
for (int i = 0; i <= temp.level; i++) {
node.route[i] = temp.route[i];
}
node.route[temp.level + 1] = 1;//上为1
if(node.level < minlevel)//进行限界,若移动次数比当前求得的最优解minlevel大,则标记为废节点
Insert(node);
}
//推箱子往下
if (map[temp.x + 1][temp.y] != '#' && Robot(map, temp.x - 1, temp.y, temp)) {
heapnode node;
node.x = temp.x + 1;
node.y = temp.y;
node.length = GetLen(node);
node.level = temp.level + 1;
for (int i = 0; i <= temp.level; i++) {
node.route[i] = temp.route[i];
}
node.route[temp.level + 1] = 2;//下为2
if (node.level < minlevel)
Insert(node);
}
//推箱子往左
if (map[temp.x][temp.y - 1] != '#' && Robot(map, temp.x, temp.y + 1, temp)) {
heapnode node;
node.x = temp.x;
node.y = temp.y - 1;
node.length = GetLen(node);
node.level = temp.level + 1;
for (int i = 0; i <= temp.level; i++) {
node.route[i] = temp.route[i];
}
node.route[temp.level + 1] = 3;//左为3
if (node.level < minlevel)
Insert(node);
}
//推箱子往右
if (map[temp.x][temp.y + 1] != '#' && Robot(map, temp.x, temp.y - 1, temp)) {
heapnode node;
node.x = temp.x;
node.y = temp.y + 1;
node.length = GetLen(node);
node.level = temp.level + 1;
for (int i = 0; i <= temp.level; i++) {
node.route[i] = temp.route[i];
}
node.route[temp.level + 1] = 4;//右为4
if (node.level < minlevel)
Insert(node);
}
}
}
}
int main() {
cin >> row >> col;
char** map = new char* [row];
for (int i = 0; i < row; i++) map[i] = new char[col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
cin >> map[i][j];
if (map[i][j] == 'T') {
INI_TX = i;
INI_TY = j;
}
if (map[i][j] == 'S') {
SX = i;
SY = j;
}
if (map[i][j] == 'B') {
map[i][j] = '.';
INI_BX = i;
INI_BY = j;
}
}
}
GetAns(map);
//for (int i = 0; i < row; i++) {
// for (int j = 0; j < col; j++) {
// cout << map[i][j] ;
// }
// cout << endl;
//}
cout << minlevel;
return 0;
}