1. 程式人生 > 其它 >題解 P3855 【[TJOI2008]Binary Land】

題解 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\) 裡。在預處理時,直接將兩隻企鵝的移動方式對應起來,這樣在移動時比較方便(詳見程式碼)。


下面是喜聞樂見的程式碼:

#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

(目前最優解)

歡迎交流討論,請點個贊哦~