松鼠推箱子是一款非常经典的游戏
那该如何实现“松鼠推箱子的最优解”呢?
目录
一、模拟地图
二、BFS算法实现
三、优化
一、模拟地图(仅廉容一个箱子)
我们以
‘# ’为墙壁
‘@’为松鼠
‘%’为箱子
‘ * ’为终点
就模拟这张图吧
Input:
12 6
. ####. . #####
##. . #. . #. . . #
#. . . ####.%. #
#. . . . * . . . . . #
##. . . . #@. .##
. ########## .
由松鼠拓展出第一层,第二层,......
宽搜部分不细讲了,不懂得可以观看宽度优先搜索
二,实现
#include<bits/stdc++.h>
using namespace std;
int r = 0 , c = 0;
int boxx = 0,boxy = 0,rx = 0,ry = 0;
char m[10000][10000];//#墙 .路 @人 %箱 *终
bool book[10000][10000];
int ans = 0;
void bfs(){
int dx[4] = {1,0,-1,0};
int dy[4] = {0,-1,0,1};
std::queue<int> x;
std::queue<int> y;
std::queue<int> bx;
std::queue<int> by;
std::queue<int> dep;
bx.push(boxx);
by.push(boxy);
x.push(rx);
y.push(ry);
dep.push(0);
while(x.empty() != 1) {
int tx = x.front();
int ty = y.front();
int tdep = dep.front();
int boxtx = bx.front();
int boxty = by.front();
x.pop(); y.pop(); dep.pop();
bx.pop(); by.pop();
for(int i=0;i<4;i++) {
int boxttx = boxtx + dx[i];
int boxtty = boxty + dy[i];
int ttx = tx + dx[i];
int tty = ty + dy[i];
if(m[ttx][tty] == '.' || m[ttx][tty] == '%' || m[ttx][tty] == '@' || m[ttx][tty] == '*') {//可走
if(ttx >= 1 && ttx <= r && tty >= 1 && tty <= c) {//越界
if(ttx == boxtx && tty == boxty) {//箱子情况
if(m[boxttx][boxtty] == '.' || m[boxttx][boxtty] == '@' || m[boxttx][boxtty] == '*') {//箱子可走
if(boxttx >= 1 && boxttx <= r && boxtty >= 1 && boxtty <= c) {//越界
bx.push(boxttx);
by.push(boxtty);
x.push(ttx);
y.push(tty);
dep.push(tdep + 1);
cout<<x.back()<<" "<<y.back()<<" "<<bx.back()<<" "<<by.back()<<" "<<dep.back()<<endl;
}
}
}
else {
bx.push(boxtx);
by.push(boxty);
x.push(ttx);
y.push(tty);
dep.push(tdep + 1);
cout<<x.back()<<" "<<y.back()<<" "<<bx.back()<<" "<<by.back()<<" "<<dep.back()<<endl;
}
}
}
if(m[bx.back()][by.back()] == '*') {
ans = dep.back();
return ;
}
}
cout<<endl;
}
ans = -1;
return ;
}
int main(){
cin>>r>>c;
for(int i=1;i<=r;i++) {
for(int j=1;j<=c;j++) {
cin>>m[i][j];
}
}
for(int i=1;i<=r;i++) {
for(int j=1;j<=c;j++) {
if(m[i][j] == '@') {
rx = j;
ry = i;
}
if(m[i][j] == '%') {
boxx = j;
boxy = i;
}
}
}
bfs();
cout<<ans<<endl;
return 0;
}
三、优化
我们会发现松鼠拓展的点之间有重复部分,所以需要把每一次拓展记录,减小拓展树。
一格附近如果有大于3个格子(除了目标点和起始点),都可以填掉,可以大大减少时间复杂度。