POJ1324 Holedox Moving(状态压缩+BFS)

链接:http://poj.org/problem?id=1324

题意,给出蛇的位置和障碍物的位置,求蛇爬到(1,1)的最少步数


一开始在做这题的时候,苦于没办法表示这个蛇的状态,用数组来存一整条蛇的位置,但是这样存很难判断是否访问过这个状态。
看了网上的博客才明白状态压缩的思路。第一次做状态压缩,因为一点小错误找了很久的错。
思路:
用一个结构体来存蛇的状态,3个数据,分别是蛇头的坐标(x,y),然后剩余的蛇身体用一个二进制数来表示。
用00,01,10,11可以表示4种状态,那么就可以将4个状态分别设置为这块身体相对于上一块身体的方向。
然后将这些二进制数连起来,所以就是一个最多14位的二进制数,转换为10进制,就能表示当前蛇的状态;
我设置的方向为go[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
那么用00,01,10,11,来表示下,上,右,左
因为表示的方向是相对于上一块身体,那么要从上一块身体往下找身体的话,就是相对的方向;
如果用B1,B2,B3来表示蛇,B1在B2的上面,那么相对的,B2在B1的下面;
所以用一个数组来设置相反方向num[4] = { 1, 0, 3, 2 };与go数组的方向对应



#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<set>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<map>
#include<cstring>
#include<iostream>
using namespace std;
int n, m, l;
int go[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
int num[4] = { 1, 0, 3, 2 };
bool vis[22][22][(1 << 14) | 1];
int pic[22][22];
int base;
struct pos{
	int x, y;
};
struct node{
	int x, y, state, step;
};
bool judge(int x, int y)//判断是否越界以及是否有障碍物
{
	if (x<1 || x>n || y<1 || y>m)
		return false;
	if (pic[x][y] == -1)
		return false;
	return true;
}
bool judgedir(int x, int y, int tx, int ty, int s)//tx,ty是目标方向,从蛇头往回找,看看是否会撞到自己身体
{
	int k;
	for (int i = 1; i < l; i++)
	{
		k = s & 3;
		s >>= 2;
		x += go[k][0];
		y += go[k][1];
		if (x == tx&&y == ty)
			return false;
	}
	return true;
}
int getstate(pos a[])//求初始状态
{
	int ans = 1;
	int i, j;
	for (i = l - 1; i >= 1; i--)
	{
		for (j = 0; j < 4; j++)
		{
			if (a[i].x == a[i - 1].x + go[j][0] && a[i].y == a[i - 1].y + go[j][1])
			{
				ans <<= 2;
				ans |= j;
				ans &= base;//去掉多余的长度
				break;
			}
		}
	}
	return ans;
}
int BFS(int x, int y, int st)
{
	queue<node> Q;
	node start, use;
	start.x = x;
	start.y = y;
	start.state = st;
	start.step = 0;
	Q.push(start);
	vis[x][y][st] = true;
	while (!Q.empty())
	{
		start = Q.front();
		Q.pop();
		if (start.x == 1 && start.y == 1)
			return start.step;
		use.step = start.step + 1;
		int i;
		for (i = 0; i < 4; i++)
		{
			use.x = start.x + go[i][0];
			use.y = start.y + go[i][1];
			if (judge(use.x, use.y) && judgedir(start.x, start.y, use.x, use.y, start.state))
			{
				use.state = start.state;
				use.state <<= 2;
				use.state |= num[i];
				use.state &= base;
				if (!vis[use.x][use.y][use.state])
				{
					vis[use.x][use.y][use.state] = true;
					Q.push(use);
				}
			}
		}
	}
	return -1;
}
int main()
{
//	freopen("D://input.txt", "r", stdin);
	int kase = 1;
	while (scanf("%d%d%d", &n, &m, &l) != EOF&&n&&m&&l)
	{
		memset(pic, 0, sizeof(pic));
		memset(vis, false, sizeof(vis));
		base = (1 << (2 * (l - 1))) - 1;//当前使用的用来表示蛇的二进制数字的长度
		pos firststate[10];//蛇身体的初始状态
		int i;
		for (i = 0; i < l; i++)
		{
			scanf("%d%d", &firststate[i].x, &firststate[i].y);
		}
		int num;
		scanf("%d", &num);
		while (num--)
		{
			int x, y;
			scanf("%d%d", &x, &y);
			pic[x][y] = -1;//障碍物设置-1
		}
		printf("Case %d: %d\n", kase++, BFS(firststate[0].x, firststate[0].y, getstate(firststate)));
	}
	return 0;
}


你可能感兴趣的:(POJ1324 Holedox Moving(状态压缩+BFS))