1. 程式人生 > >uva 1601 The Morning after Halloween code2

uva 1601 The Morning after Halloween code2

題意:有n個用小寫字母表示的鬼和一張地圖,每個鬼都要移動到對應的大寫字母兩個鬼的位置不能在一次移動中交換,問最少步數。

思路:

雙向bfs。此題還可以單向bfs,見code1

1、先將地圖用圖的方法表示,即在每一個空白(包括大小寫字母)和四周的空白連上一條邊,用單個整數表示一個空白。

2、雙向bfs。即從開始和結束都進行bfs,相遇時把兩次的走過的路徑長加起來就是結果。

參考:

http://blog.csdn.net/qq_29169749/article/details/51420097

http://blog.csdn.net/crazysillynerd/article/details/42681579

程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<sstream>
#include<queue>
using namespace std;

#define N 20
#define Num 3
#define m_step 200

int n,m,num;
int Start[Num],End[Num];
vector<int> g[N*N];
int cnt=0;
int step[m_step][m_step][m_step];
int color[m_step][m_step][m_step];

struct Node {
	int x[Num];
	Node() {}
	Node(int xx[]) {
		for(int i=0; i<num; i++) x[i]=xx[i];
	}
	Node(int one,int two,int three) {
		x[0]=one,x[1]=two,x[2]=three;
	}
	bool operator ==(const Node& other) const {
		for(int i=0; i<num; i++) {
			if(x[i]!=other.x[i]) return false;
		}
		return true;
	}
};

void init() {
	cnt=0;
	for(int i=0; i<N*N; i++) g[i].clear(),g[i].push_back(i);
	memset(step,-1,sizeof(step));
	memset(Start,0,sizeof(Start));
	memset(End,0,sizeof(End));
	memset(color,0,sizeof(color));
}

void make_G(char a[N][N]) {
	int fill[N][N]= {0};
	memset(fill,0,sizeof(fill));
	for(int i=0; i<n; i++) {
		for(int j=0; j<m; j++) {
			if(a[i][j]!='#') {
				fill[i][j]=++cnt;
				if(i!=0&&a[i-1][j]!='#') g[cnt].push_back(fill[i-1][j]),g[fill[i-1][j]].push_back(cnt);
				if(j!=0&&a[i][j-1]!='#') g[cnt].push_back(fill[i][j-1]),g[fill[i][j-1]].push_back(cnt);
			}
		}
	}
	int S[26]= {0},E[26]= {0};
	memset(S,0,sizeof(S));
	for(int i=0; i<n; i++) {
		for(int j=0; j<m; j++) {
			if('A'<=a[i][j]&&a[i][j]<='Z') {
				E[a[i][j]-'A']=fill[i][j];
			}
			if('a'<=a[i][j]&&a[i][j]<='z') {
				S[a[i][j]-'a']=fill[i][j];
			}
		}
	}
	int s=-1;
	for(int i=0; i<26; i++) {
		if(S[i]) {
			++s;
			Start[s]=S[i];
			End[s]=E[i];
		}
	}
}

void dbfs() {
	Node IN=Node(Start),OUT=Node(End);
	queue<Node> quef,queb;
	quef.push(IN),queb.push(OUT);
	step[IN.x[0]][IN.x[1]][IN.x[2]]=0;
	step[OUT.x[0]][OUT.x[1]][OUT.x[2]]=0;
	while(!quef.empty()&&!queb.empty()) {

		int T=quef.size();
		while(T--) {
			Node head=quef.front();
			quef.pop();
			int a=head.x[0],b=head.x[1],c=head.x[2];
			for(int i=0; i<g[a].size(); i++) {
				for(int j=0; j<g[b].size(); j++) {
					if(g[a][i]==g[b][j]||(a==g[b][j]&&b==g[a][i])) continue;
					for(int k=0; k<g[c].size(); k++) {
						int a2=g[a][i],b2=g[b][j],c2=g[c][k];
						if((a2==c2||c2==b2||(a==c2&&c==a2)||(b==c2&&c==b2))&&c!=0) continue;
						if(color[a2][b2][c2]==0) {
							step[a2][b2][c2]=step[a][b][c]+1;
							color[a2][b2][c2]=1;
							quef.push(Node(a2,b2,c2));
						} else if(color[a2][b2][c2]==2) {
							printf("%d\n",step[a2][b2][c2]+step[a][b][c]-1);
							return;
						}
					}
				}
			}
		}

		T=queb.size();	//注意在此處更新 
		while(T--) {
			Node head=queb.front();
			queb.pop();
			int a=head.x[0],b=head.x[1],c=head.x[2];
			for(int i=0; i<g[a].size(); i++) {
				for(int j=0; j<g[b].size(); j++) {
					if(g[a][i]==g[b][j]||(a==g[b][j]&&b==g[a][i])) continue;
					for(int k=0; k<g[c].size(); k++) {
						int a2=g[a][i],b2=g[b][j],c2=g[c][k];
						if((a2==c2||c2==b2||(a==c2&&c==a2)||(b==c2&&c==b2))&&c!=0) continue;
						if(color[a2][b2][c2]==0) {
							step[a2][b2][c2]=step[a][b][c]+1;
							color[a2][b2][c2]=2;
							queb.push(Node(a2,b2,c2));
						} else if(color[a2][b2][c2]==1) {
							printf("%d\n",step[a2][b2][c2]+step[a][b][c]-1);
							return;
						}
					}
				}
			}
		}

	}
}

int main() {
	while(scanf("%d%d%d",&m,&n,&num)==3&&n&&m&&num) {
		init();
		char a[N][N];
		for(int i=0; i<n; i++) {
			getchar();
			fgets(a[i],m+1,stdin);
		}
		make_G(a);
		dbfs();
	}
	return 0;
}