农夫约翰的奶牛在农场周围造成了太多麻烦,因此约翰希望对它们保持更密切的关注。
通过在农场的各个位置安装 个反光围栏,他希望能够从 位置的房子看到 位置的牛棚。
在约翰农场的二维平面图中,围栏 i 表示为以整数位置坐标 为中心的倾斜 度(如 /
或 \
)的短线段。
例如,以 为中心,形如 /
的围栏可以描述为从 到 的线段。
每个围栏(以及牛棚的位置)位于不同的位置。
和 处无围栏。
约翰计划坐在他的房屋 处,并直接向右(沿 方向)看。
当他的目光从农场的一些反光围栏上反射出来时,他希望能够看到点 。
不幸的是,他认为其中一个反光围栏的摆放朝向不对,例如应该为 /
,却摆成了 \
。
请输出给定反光围栏中,第一个能够通过改变其朝向使得约翰成功看到点 的围栏的顺序编号。
如果约翰不需要切换任何围栏的朝向就已经可以看到点 则输出 。
如果约翰无法通过切换单个围栏的朝向使自己看到点 (a,b) 则输出 。
输入格式
第一行包含三个整数 。
接下来 行,其中第 行描述第 号围栏的位置和朝向。首先包含两个整数 表示其中心点位置,然后包含一个字符 /
或 \
表示围栏朝向。
围栏编号从 开始。
输出格式
输出第一个能够通过改变其朝向使得约翰成功看到点 的围栏的顺序编号。
如果约翰不需要切换任何围栏的朝向就已经可以看到点 则输出 。
如果约翰无法通过切换单个围栏的朝向使自己看到点 则输出 。
数据范围
输入样例:
5 6 2
3 0 /
0 2 /
1 2 /
3 2 \
1 3 \
输出样例:
4
样例解释
农场的平面图如下所示,其中 表示约翰的房子, 表示牛棚:
3 .\.....
2 //.\..B
1 .......
0 H../...
0123456
通过改变 处的围栏朝向,就可以使约翰看到点 ,如下所示:
3 .\.....
2 //./--B
1 ...|...
0 H--/...
0123456
可以发现一个镜子只有两个度,所以每个镜子最多被遍历两次,将目标点视为一个节点,所以共有 N + 1 个节点,所以如果没陷入循环,则最多前进 2(N + 1)次。
可以枚举改变每一面镜子,然后对于当前这次枚举,从 (0,0) 点开始出发,枚举所有能走到的下一个镜子,取最近的那个,然后更新当前所在的镜子和方向!
using namespace std;
const int N = 210, INF = 1e8;
int n;
struct Mirror{
int x, y;
char c;
}q[N];
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
void rotate(char &c){
if(c == '/') c = '\\';
else c = '/';
}
bool check(){
int d = 1, k = 0;
for(int i = 0; i < 2 * (n + 1); i++){
int id = -1, len = INF;
for(int j = 1; j <= n + 1; j++){
if(k == j) continue;
if(q[k].x + abs(q[k].x - q[j].x) * dx[d] != q[j].x) continue;
if(q[k].y + abs(q[k].y - q[j].y) * dy[d] != q[j].y) continue;
int t = abs(q[k].x - q[j].x) + abs(q[k].y - q[j].y);
if(t < len) len = t, id = j;
}
if(id == -1) return false;
if(id == n + 1) return true;
k = id;
if(q[id].c == '/') d ^= 1;
else d ^= 3;
}
return false;
}
int main(){
cin >> n;
cin >> q[n + 1].x >> q[n + 1].y;
for(int i = 1; i <= n; i++)
cin >> q[i].x >> q[i].y >> q[i].c;
if(check()) puts("0");
else{
for(int i = 1; i <= n; i++){
rotate(q[i].c);
if(check()){
cout << i << endl;
return 0;
}
rotate(q[i].c);
}
puts("-1");
}
return 0;
}