紫书 万圣节后的早晨 UVa1601

在这里插入图片描述
参考了刘汝佳老师的代码,但没有对空格编号。优点是写代码和调试时更为直观,但需要开较大的vis数组。

#include<iostream>
#include<string>
#include<cassert>
#include<algorithm>
#include<map>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<set>
#include<queue>
using namespace std;
struct pos
{
	int x;
	int y;
	pos(int x=0,int y=0):x(x),y(y){}
	pos(const pos& p) {
		x = p.x;
		y = p.y;
	}
};
const int maxn = 16;
int grid[maxn][maxn];
map<char, pos>ori;
map<char, pos>fin;
pos s[3], t[3];
int vis[maxn * maxn][maxn * maxn][maxn * maxn];
int w, h, n;
pos operator+(const pos& p1, const pos& p2)
{
	return pos(p1.x + p2.x, p1.y + p2.y);
}
bool operator==(const pos& p1,const pos& p2)
{
	return p1.x == p2.x && p1.y == p2.y;
}
pos dir[5] = { {0,0}, {-1,0},{0,1},{1,0},{0,-1} };
pos G[maxn * maxn][5];
int deg[maxn * maxn];
inline int postoith(const pos& p)
{
	return p.x * w + p.y;
}
void read_grid(int w,int h)
{
	memset(G, 0, sizeof(G));
	memset(deg, 0, sizeof(deg));
	for (int i = 0; i < 3; ++i)
	{
		s[i].x = s[i].y = t[i].x = t[i].y = 0;
	}
	getchar();
	for (int i = 0; i < h; ++i)
	{
		char temp[20];
		fgets(temp, 20, stdin);
		for (int j = 0; j < w; ++j)
		{
			char input = temp[j];
			if (input == '#' || input == ' ')
				grid[i][j] = input;
			else if (islower(input))
			{
				s[input - 'a'] = pos(i, j);
				grid[i][j] = ' ';
			}
			else if (isupper(input))
			{
				t[input - 'A'] = pos(i, j);
				grid[i][j] = ' ';
			}
		}
	}
	for (int i = 0; i < h; ++i)
	{
		for (int j = 0; j < w; ++j)
		{
			if (grid[i][j] == ' ')
			{
				pos c(i, j);
				int k2 = 0;
				for (int k = 0; k < 5; ++k)
				{
					pos t = c + dir[k];
					if (grid[t.x][t.y] == ' ')
						G[i * w + j][k2++] = t;
				}
				deg[i * w + j] = k2;
			}
		}
	}
	deg[0] = 1;
}
bool conflict(const int a, const int b, const int a2, const int b2)
{
	return a2 == b2 || (a == b2 && b == a2);
}
int bfs()
{
	memset(vis, -1, sizeof(vis));
	int a = postoith(s[0]), b = postoith(s[1]), c = postoith(s[2]);
	vis[a][b][c] = 0;
	int code = (a << 16) + (b << 8) + c;
	queue<int>q;
	q.push(code);
	while (!q.empty())
	{
		code = q.front(); q.pop();
		c = code & ((1 << 8) - 1), b = (code >> 8) & ((1 << 8) - 1), a = (code >> 16) & ((1 << 8) - 1);
		pos pa(a / w, a % w), pb(b / w, b % w), pc(c / w, c % w);
		if (pa == t[0] && pb == t[1] && pc == t[2])
		{
			return vis[postoith(t[0])][postoith(t[1])][postoith(t[2])];
		}
		int dega = deg[a];
		int degb = deg[b];
		int degc = deg[c];
		for (int i = 0; i < dega; ++i)
		{
			pos pa2 = G[a][i];
			int a2 = postoith(pa2);
			for (int j = 0; j < degb; ++j)
			{
				pos pb2 = G[b][j];
				int b2 = postoith(pb2);
				if (conflict(a, b, a2, b2))
					continue;
				for (int k = 0; k < degc; ++k)
				{
					pos pc2 = G[c][k];
					int c2 = postoith(pc2);
					if (a == a2 && b == b2 && c == c2)continue;
					if (-1 == vis[a2][b2][c2] && !conflict(a, c, a2, c2) && (!conflict(b, c, b2, c2) || n==1))
					{
						vis[a2][b2][c2] = vis[a][b][c] + 1;
						q.push((a2 << 16) + (b2 << 8) + c2);
					}
				}
			}
		}
	}
	return -1;
}
int main()
{
	//freopen("input.txt", "r", stdin);// freopen("output2.txt", "w", stdout);
	while (scanf("%d%d%d",&w,&h,&n) && w != 0 && h != 0 && n != 0)
	{
		read_grid(w, h);
		printf("%d\n", bfs());
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的程序

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值