uva 1601 dbfs搜索

#include <bits/stdc++.h>
using namespace std;
const int maxn = 16 + 10, maxm = 192 + 10;
int cx[] = { -1, 1, 0, 0, 0}, cy[] = {0, 0, -1, 1, 0}, w, h, n, cnt;
int id[maxn][maxn], G[maxm][5], st[3], ed[3], edge[maxm], d[maxm][maxm][maxm];
struct ghost
{
	int a, b, c;
	ghost(int aa, int bb, int cc): a(aa), b(bb), c(cc) {}
};
inline bool ok(int a, int b, int a1, int b1)
{
	return ((a1 == b1) || (a1 == b && b1 == a));
}
void bfs()
{
	queue<ghost>q;
	q.push(ghost(st[0], st[1], st[2]));
	d[st[0]][st[1]][st[2]] = 0;
	while (!q.empty())
	{
		ghost u = q.front(); q.pop();
		if (u.a == ed[0] && u.b == ed[1] && u.c == ed[2]) return;
		for (int i = 1, a1 = G[u.a][i]; i <= edge[u.a]; ++i, a1 = G[u.a][i])
			for (int j = 1, b1 = G[u.b][j]; j <= edge[u.b];  ++j, b1 = G[u.b][j])
				if (!ok(u.a, u.b, a1, b1))
					for (int k = 1, c1 = G[u.c][k]; k <= edge[u.c]; c1 = G[u.c][k], ++k, c1 = G[u.c][k])
						if (!(ok(u.a, u.c, a1, c1) || ok(u.b, u.c, b1, c1)) && d[a1][b1][c1] == -1)
						{
							d[a1][b1][c1] = d[u.a][u.b][u.c] + 1;
							q.push(ghost(a1, b1, c1));
						}
	}
}
int main(int argc, char const * argv[])
{
	char M[maxn][maxn];
	ios::sync_with_stdio(false);
	while (cin >> w >> h >> n && n)
	{
		cnt = 0;
		int x[maxm], y[maxm];
		memset(edge, 0, sizeof(edge));
		memset(d, -1, sizeof(d));
		cin.get(); cin.get();
		for (int i = 0; i < h; i++)
			cin.getline(M[i], 20);
		for (int i = 0; i < h; i++)
			for (int j = 0; j < w; j++)
				if (M[i][j] != '#')
				{
					id[i][j] = ++cnt;//利用矩阵存储稀疏图 , cnt为每个节点的编号
					x[cnt] = i, y[cnt] = j;
					if ('a' <= M[i][j] && M[i][j] <= 'c')
						st[M[i][j] - 'a'] = cnt;//找到起始点
					if ('A' <= M[i][j] && M[i][j] <= 'C')
						ed[M[i][j] - 'A'] = cnt;//找到终止点
				}
		for (int i = 1; i <= cnt; i++)
			for (int j = 0; j < 5; j++)//使用edge存储第i个节点具有的相邻节点数
				if (M[x[i] + cx[j]][y[i] + cy[j]] != '#')//遍历五个方向,寻找每个节点的相邻节点
					G[i][++edge[i]] = id[x[i] + cx[j]][y[i] + cy[j]];//第五个是自身
		for (int i = 2; i > 0; i--)
			if (n <= i)
			{
				edge[++cnt] = 1;
				G[cnt][1] = cnt;
				st[i] = ed[i] = cnt;
			}//补充虚拟节点,在判断非法情况是起作用
		bfs();
		cout << d[ed[0]][ed[1]][ed[2]] << endl;
	}
	return 0;
}



学这道题,花费了我大量的精力,题目真是相当经典

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值