算法题(镜子)

149 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

镜子

题目描述

农夫约翰的奶牛在农场周围造成了太多麻烦,因此约翰希望对它们保持更密切的关注。

通过在农场的各个位置安装 NN 个反光围栏,他希望能够从 (0,0)(0,0) 位置的房子看到 (a,b)(a,b) 位置的牛棚。

在约翰农场的二维平面图中,围栏 ii 表示为以整数位置坐标 (xi,yi)(xi,yi) 为中心的倾斜 4545 度(如 / 或 ``)的短线段。

例如,以 (3,5)(3,5) 为中心,形如 / 的围栏可以描述为从 (2.9,4.9)(2.9,4.9) 到 (3.1,5.1)(3.1,5.1) 的线段。

每个围栏(以及牛棚的位置)位于不同的位置。

(0,0)(0,0) 和 (a,b)(a,b) 处无围栏。

约翰计划坐在他的房屋 (0,0)(0,0) 处,并直接向右(沿 +x+x 方向)看。

当他的目光从农场的一些反光围栏上反射出来时,他希望能够看到点 (a,b)(a,b)。

不幸的是,他认为其中一个反光围栏的摆放朝向不对,例如应该为 /,却摆成了 ``。

请输出给定反光围栏中,第一个能够通过改变其朝向使得约翰成功看到点 (a,b)(a,b) 的围栏的顺序编号。

如果约翰不需要切换任何围栏的朝向就已经可以看到点 (a,b)(a,b) 则输出 00。

如果约翰无法通过切换单个围栏的朝向使自己看到点 (a,b)(a,b) 则输出 −1−1。

输入格式

第一行包含三个整数 N,a,bN,a,b。

接下来 NN 行,其中第 ii 行描述第 ii 号围栏的位置和朝向。首先包含两个整数 xi,yixi,yi 表示其中心点位置,然后包含一个字符 / 或 `` 表示围栏朝向。

围栏编号从 11 开始。

输出格式

输出第一个能够通过改变其朝向使得约翰成功看到点 (a,b)(a,b) 的围栏的顺序编号。

如果约翰不需要切换任何围栏的朝向就已经可以看到点 (a,b)(a,b) 则输出 00。

如果约翰无法通过切换单个围栏的朝向使自己看到点 (a,b)(a,b) 则输出 −1−1。

数据范围

1≤N≤2001≤N≤200,
−106≤xi,yi,a,b≤106−106≤xi,yi,a,b≤106

输入样例:

5 6 2
3 0 /
0 2 /
1 2 /
3 2 \
1 3 \

输出样例:

4

样例解释

农场的平面图如下所示,其中 HH 表示约翰的房子,BB 表示牛棚:

3 ......
2 //...B
1 .......
0 H../...
  0123456

通过改变 (3,2)(3,2) 处的围栏朝向,就可以使约翰看到点 (a,b)(a,b),如下所示:

3 ......
2 //./--B
1 ...|...
0 H--/...
  0123456

代码

#include <bits/stdc++.h>
using namespace std;
const int D[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
const int T[2][4]={{3,2,1,0},{1,0,3,2}};
int n;
int mx,my;
vector<int> ax,ay;
int tag[205][205];
bool st[205][205][4];
bool rt[205];
struct Node
{
    int x=0,y=0,id=-1;
    void f()
    {
        x=lower_bound(ax.begin(), ax.end(), x)-ax.begin()+1;
        y=lower_bound(ay.begin(), ay.end(), y)-ay.begin()+1;
    }
    void input(int i)
    {
        cin>>y>>x;
        id=i;
    }
}pt[205];
void f(vector<int> &v)
{
    sort(v.begin(),v.end());
    v.resize(unique(v.begin(),v.end())-v.begin());
}

bool sol()
{
    memset(st,0,sizeof st);
    bool flag=0;
    int d=1;
    int x=pt[n+1].x,y=pt[n+1].y;
    while(1){
        if(x==pt[0].x&&y==pt[0].y){
            flag=1;
            break;
        }
        if(x<1||x>mx||y<1||y>my||st[x][y][d])break;
        st[x][y][d]=1;
        if(tag[x][y]!=-1)d=T[tag[x][y]][d];
        x+=D[d][0],y+=D[d][1];
    }
    return flag;
}
int main()
{
    cin>>n;
    pt[0].input(0);
    for(int i=1;i<=n;i++){
        pt[i].input(i);
        char c;
        cin>>c;
        rt[i]=(c=='/');
    }
    for(int i=0;i<=n+1;i++){
        ax.push_back(pt[i].x);
        ay.push_back(pt[i].y);
    }
    f(ax),f(ay);
    mx=ax.size(),my=ay.size();
    memset(tag,-1,sizeof tag);
    for(int i=0;i<=n+1;i++){
        pt[i].f();
        if(i>=1&&i<=n)tag[pt[i].x][pt[i].y]=rt[pt[i].id];
    }
    if(sol()){
        cout<<0;
        return 0;
    }
    for(int i=1;i<=n;i++){
        tag[pt[i].x][pt[i].y]^=1;
        if(sol()){
            cout<<i;
            return 0;
        }
        tag[pt[i].x][pt[i].y]^=1;
    }
    cout<<-1;
}