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

原想法:

结果运行了2秒多,查了下别人的题解大多都只有30至40ms,然后查了下题解发现了个有趣的解法,设置一个专属值记录所有经历过的状态

#include
using namespace std;
char arr[12][12];
int sum;
struct hhh
{
	int x;
	int y;
	int temp;
}f, c;
void shuru();
void ren(hhh&);
int main()
{
	freopen("title.in", "r", stdin);
	shuru();
	while (true)
	{
		ren(f);
		ren(c);
		if (f.x == c.x && f.y == c.y)
		{
			cout << sum / 2;//因为牛和人的操作是同时的,而同一步操作,sum被加1了两次,所以要/2
			break;
		}
		if (sum > 100000000)//大于某一个数值说明循环
		{
			cout << 0;
			return 0;
		}
	}
}
void shuru()
{
	for (int i = 1; i <= 10; i++)
	{
		for (int d = 1; d <= 10; d++)
		{
			cin >> arr[i][d];
			if (arr[i][d] == 'F')
			{
				f.x = i;
				f.y = d;
				f.temp = 1;
				arr[i][d] = '.';
			}
			if (arr[i][d] == 'C')
			{
				c.x = i;
				c.y = d;
				c.temp = 1;
				arr[i][d] = '.';
			}
		}
	}
}
void ren(hhh& g)
{
	int gx = g.x, gy = g.y;//判断前方是否有障碍,如果有则转向,没有则该方向前进
	if (arr[gx - 1][gy] != '.' && g.temp == 1)
	{
		g.temp = 2;
	}
	else if (arr[gx][gy + 1] != '.' && g.temp == 2)
	{
		g.temp = 3;
	}
	else if (arr[gx + 1][gy] != '.' && g.temp == 3)
	{
		g.temp = 4;
	}
	else if (arr[gx][gy - 1] != '.' && g.temp == 4)
	{
		g.temp = 1;
	}
	else
	{
		if (g.temp == 1)
			g.x -= 1;
		else if (g.temp == 2)
			g.y += 1;
		else if (g.temp == 3)
			g.x += 1;
		else if (g.temp == 4)
			g.y -= 1;
	}//在二维坐标中x方向向下,y方向想右
	sum++;//不管是什么操作都要+1;
}

 判断是否相遇:给每一个状态设定一个专属值,如果这个值之前已经出现过,说明他们陷入了循环,不能相遇。每个状态都要保存决定状态的所有元素,如坐标上行走的牛,你要记录的状态右它的坐标和方向。此题则要保存农夫和牛各自的x,y坐标和方向。代码如下:

temp = f.x * 100000 + f.y * 10000 + c.x * 1000 + c.y * 100 + f.temp * 10 + c.temp;
		//设置专属值,避免循环
		if (memory[temp])//如果专属值出现两次则代表牛和人已经陷入循环
		{
			cout << "0" << endl;
			break;
		}
		else
			memory[temp] = 1;

修改后的完整代码,运行时间30ms: 

#include
using namespace std;
char arr[12][12];
int sum, memory[1600005];
struct hhh
{
	int x;
	int y;
	int temp;
}f, c;
void shuru();
void ren(hhh&);
int main()
{

	shuru();
	int temp = 0;
	while (true)
	{
		ren(f);
		ren(c);
		if (f.x == c.x && f.y == c.y)
		{
			cout << sum / 2;
			break;
		}
		temp = f.x * 100000 + f.y * 10000 + c.x * 1000 + c.y * 100 + f.temp * 10 + c.temp;
		//设置专属值,避免循环
		if (memory[temp])//如果专属值出现两次则代表牛和人已经陷入循环
		{
			cout << "0" << endl;
			break;
		}
		else
			memory[temp] = 1;
	}

}
void shuru()
{
	for (int i = 1; i <= 10; i++)
	{
		for (int d = 1; d <= 10; d++)
		{
			cin >> arr[i][d];
			if (arr[i][d] == 'F')
			{
				f.x = i;
				f.y = d;
				f.temp = 1;
				arr[i][d] = '.';
			}
			if (arr[i][d] == 'C')
			{
				c.x = i;
				c.y = d;
				c.temp = 1;
				arr[i][d] = '.';
			}
		}
	}
}
void ren(hhh& g)
{
	int gx = g.x, gy = g.y;//判断前方是否有障碍
	if (arr[gx - 1][gy] != '.' && g.temp == 1)
	{
		g.temp = 2;
	}
	else if (arr[gx][gy + 1] != '.' && g.temp == 2)
	{
		g.temp = 3;
	}
	else if (arr[gx + 1][gy] != '.' && g.temp == 3)
	{
		g.temp = 4;
	}
	else if (arr[gx][gy - 1] != '.' && g.temp == 4)
	{
		g.temp = 1;
	}
	else
	{
		if (g.temp == 1)
			g.x -= 1;
		else if (g.temp == 2)
			g.y += 1;
		else if (g.temp == 3)
			g.x += 1;
		else if (g.temp == 4)
			g.y -= 1;
	}
	sum++;
}

你可能感兴趣的:(洛谷刷题,学习)