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 <iostream>
#include <cstdio>
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;
}