P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two 个人刷题009

P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two

P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two

题解

模拟题。考察的点主要有两个,边界判断,简单的做法是开二维数组开为12*12的,再最外面一圈全部赋值为’*‘
第二个问题是如何判断重复。对于这样一个持续移动的状态而言,如果某个状态出现了两次:C和F在相同的位置相同的方向,那么就可以说明陷入了循环之中。简单思考的方法是记录所有的移动状态,每次移动后查表。但这样的代价太过高昂,时间复杂度过高。可以利用hash的思想,为每个状态生成一个标定值,这样就可以在O(1)的时间内进行判定了。

record[C.x + C.y * 10 + F.x * 100 + F.y * 1000 + C.dir * 10000 + F.dir * 40000] ++;

#include 
#include 
using namespace std;

struct status
{
	int x;
	int y;
	int dir;	//0向上,1向右,2向下,3向左
};

typedef status STATUS;
char map[12][12] = { 0 };
int record[8000000] = { 0 };

void mapInit()
{
	for (int i = 0; i <= 11; i++)
	{
		map[0][i] = '*';
		map[11][i] = '*';
		map[i][0] = '*';
		map[i][11] = '*';
	}
}
void move(STATUS& s, STATUS& t)
{
	if (s.dir == 0 )
	{
		if(map[s.x - 1][s.y] != '*')	//可以向上移动
			s.x -= 1;
		else
		{
			s.dir = (s.dir + 1) % 4;
		}
	}
	else if (s.dir == 1)
	{
		if (map[s.x][s.y + 1] != '*')	//可以向右移动
			s.y += 1;
		else
		{
			s.dir = (s.dir + 1) % 4;
		}
	}
	else if (s.dir == 2)
	{
		if (map[s.x + 1][s.y] != '*')	//可以向下移动
			s.x += 1;
		else
		{
			s.dir = (s.dir + 1) % 4;
		}
	}
	else if (s.dir == 3)
	{
		if (map[s.x][s.y - 1] != '*')	//可以向左移动
			s.y -= 1;
		else
		{
			s.dir = (s.dir + 1) % 4;
			return;
		}
	}
}
int main()
{
	STATUS F;
	STATUS C;
	F.x = 0;
	F.y = 0;
	C.x = 0;
	C.y = 0;
	F.dir = 0;
	C.dir = 0;
	int count = 0;

	mapInit();

	for (int i = 1; i <= 10; i++)
	{
		for (int j = 1; j <= 10; j++)
		{
			cin >> map[i][j];
			if (map[i][j] == 'C')
			{
				C.x = i;
				C.y = j;
			}
			else if (map[i][j] == 'F')
			{
				F.x = i;
				F.y = j;
			}
		}
	}

	while (C.x != F.x || C.y != F.y)
	{
		record[C.x + C.y * 10 + F.x * 100 + F.y * 1000 + C.dir * 10000 + F.dir * 40000] ++;
		move(C,F);
		move(F,C);
		if(record[C.x + C.y * 10 + F.x * 100 + F.y * 1000 + C.dir * 10000 + F.dir * 40000] != 0)
		{
			count = 0;
			break;
		}
		else
		{
			count++;
		}
	}
	printf("%d\n", count);
	return 0;
}

你可能感兴趣的:(模拟/高精度)