题解 P3855 【[TJOI2008]Binary Land】

题目传送门

算法分析:BFS

显然是爆搜题(虽然不知道为什么有 dp 标签)(雾)。

首先是状态,我们应该记录两只企鹅的位置和走到当前状态所需的步数,如果走过这个状态,那么不再重复走。

struct P {
	int x,y,a,b,step;//位置,步数 
}g,m;

其次是对状态的可行性检查。我在检查状态完毕后直接对状态进行了修改,这样可以使 BFS 主体简短一点。

inline bool check(int &x,int &y,int &a,int &b,P t) {
	//t 是没移动之前的状态 
	if(pc[x][y]=='X'||pc[a][b]=='X'){//蜘蛛网,失败 
		vis[x][y][a][b]=1;
		return false;
	}
	if(pc[x][y]=='#')vis[x][y][a][b]=1,x=t.x,y=t.y;//其中一只撞到了,就往回退 
	if(pc[a][b]=='#')vis[x][y][a][b]=1,a=t.a,b=t.b;//另一只... 
	if(vis[x][y][a][b])return false;//如果两只都撞到了,那么vis一定被标记过,退出 
	vis[x][y][a][b]=1;//没走过的状态,标记一下 
	return true;
}

最后是一些小技巧。比如说,预处理两只企鹅的移动,记录在数组 \(g_1\)\(g_2\) 里。在预处理时,直接将两只企鹅的移动方式对应起来,这样在移动时比较方便(详见代码)。


code:

#include<bits/stdc++.h>
#define reg register
using namespace std;
const int N=50;
bool vis[N][N][N][N];
char pc[N][N];
int g1[10][2] {1,0,0,-1,0,1,-1,0};
int g2[10][2] {1,0,0,1,0,-1,-1,0};
//g1 和 g2 在储存时直接对应起来 
struct P {
	int x,y,a,b,step;//位置,步数 
}g,m;
inline bool check(int &x,int &y,int &a,int &b,P t) {
	//t 是没移动之前的状态 
	if(pc[x][y]=='X'||pc[a][b]=='X'){//蜘蛛网,失败 
		vis[x][y][a][b]=1;
		return false;
	}
	if(pc[x][y]=='#')vis[x][y][a][b]=1,x=t.x,y=t.y;//其中一只撞到了,就往回退 
	if(pc[a][b]=='#')vis[x][y][a][b]=1,a=t.a,b=t.b;//另一只... 
	if(vis[x][y][a][b])return false;//如果两只都撞到了,那么vis一定被标记过,退出 
	vis[x][y][a][b]=1;//没走过的状态,标记一下 
	return true;
}
inline void bfs(int xx,int yy,int aa,int bb) {
	queue<P> q;
	q.push({xx,yy,aa,bb,0});
	vis[xx][yy][aa][bb]=1;
	while(!q.empty()) {
		reg P t=q.front();
		q.pop();
		for(reg int i=0; i<4; i++) {
			reg int x=t.x+g1[i][0],y=t.y+g1[i][1];//移动 
			reg int a=t.a+g2[i][0],b=t.b+g2[i][1];
			if(check(x,y,a,b,t)) {
				if(pc[x][y]=='T'&&pc[a][b]=='T') {//走到终点了 
					printf("%d",t.step+1);
					exit(0);
				}
				q.push({x,y,a,b,t.step+1});
			}
		}
	}
}
int main() {
	cin.tie(0);
	reg int r,c;
	cin>>r>>c;
	for(reg int i=1;i<=r;i++){
		for(reg int j=1;j<=c;j++){
			cin>>pc[i][j];
			if(pc[i][j]=='G')g={i,j};//Gurin位置 
			if(pc[i][j]=='M')m={i,j};//Malon位置 
		}
	}
	bfs(g.x,g.y,m.x,m.y);
	cout<<"no";
	return 0;
}

AC

(目前最优解)

欢迎交流讨论,请点个赞哦~

posted @ 2021-06-23 13:29  Maplisky  阅读(51)  评论(0编辑  收藏  举报