题目:
w*h 网格上有n (n<=3) 个小写字母,要求把他们分别移动到对应的大写字母里。每步可以有多个鬼同时移动(往上下左右移动,也可以不动,移动是独立的),每步结束后两个鬼不能占用同一个位置,也不能在一步之内交换位置。
要点:
- 建立新的有向图
下面给出两种做法,在UVA上分别以 1000ms 和 750ms 左右通过, 双向bfs快了不多。
bfs:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int s[3], t[3];
int dx[] = {
0, 1, 0, -1, 0};
int dy[] = {
1, 0, -1, 0, 0};
int deg[300];
int G[300][300];
struct Node {
int c1, c2, c3;
};
inline bool confict(int a1, int b1, int a2, int b2) {
return a2 == b2 || (a1 == b2 && b1 == a2);
}
int d[300][300][300];
int bfs() {
memset(d, -1, sizeof(d));
queue<Node> q;
Node begin;
begin.c1 = s[0];
begin.c2 = s[1];
begin.c3 = s[2];
q.push(begin);
d[s[0]][s[1]][s[2]] = 0;
while(!q.empty()) {
Node n = q.front();
q.pop();
int c1 = n.c1;
int c2 = n.c2;
int c3 = n.c3;
if(c1 == t[0] && c2 == t[1] && c3 == t[2]) return d[c1][c2][c3];
for(int i = 0; i < deg[c1]; i++) {
int c11 = G[c1][i];
for(int j = 0; j < deg[c2]; j++) {
int c21 = G[c2][j];
if(confict(c1, c2, c11, c21)) continue;
for(int z = 0; z < deg[c3]; z++) {
int c31 = G[c3][z];
if(confict(c1, c3, c11, c31)) continue;
if(confict(c2, c3, c21, c31)) continue;
if(d[c11][c21][c31] != -1) continue;
Node nn;
nn.c1 = c11; nn.c2 = c21