789. 逃脱阻碍者 中等 曼哈顿距离

2021.08.22 签到题

个人思路:朴素BFS

  1. 对于玩家而言,每次往集合A中加入上下左右四个点,并删去该点,这里我认为玩家不动是没啥意义的,加入的点表示走n步后,当前玩家可能所在的点位。
  2. 对于阻碍者而言,每次往另一个集合B中加入上下左右四个点,保留当前的点,相当于得到了一个区域范围。
  3. 玩家当前的位置不能在区域范围内,如果某个点在阻碍者集合B中,删去该点,即求A-(A∩B)
    1. 如果A-(A∩B)为空时,表示不能逃出。
    2. 如果A-(A∩B)中有终点,表示逃出。

动手实现试试。

class Solution {
public:
    struct node{
        int x;
        int y;
        node(int _x,int _y):x(_x),y(_y){}
        bool operator < (const node & temp)const{
            if(x==temp.x)return y<temp.y;
            else return x<temp.x;
        }
    };

    int X[4]={0,0,1,-1};
    int Y[4]={1,-1,0,0};

    bool escapeGhosts(vector<vector<int> >& ghosts, vector<int>& target) {
        set<node> A;
        set<node> B;
        for(int i=0;i<ghosts.size();i++){
            B.insert(node(ghosts[i][0],ghosts[i][1]));
        }
        A.insert(node(0,0));
        if(target[0]==0&target[1]==0)return true;
        while(1){
            set<node> temp_A;
            for(set<node>::iterator iter=A.begin();iter!=A.end();iter++){
                for(int i=0;i<4;i++){
                    temp_A.insert(node(iter->x+X[i],iter->y+Y[i]));
                }
            }
            set<node> temp_B;
            for(set<node>::iterator iter=B.begin();iter!=B.end();iter++){
                for(int i=0;i<4;i++){
                    temp_B.insert(node(iter->x+X[i],iter->y+Y[i]));
                }
            }
            B.insert(temp_B.begin(),temp_B.end());
            set<node> temp1,temp2;
            set_intersection(temp_A.begin(),temp_A.end(),B.begin(),B.end(),inserter(temp1,temp1.begin()));
            set_difference(temp_A.begin(),temp_A.end(),temp1.begin(),temp1.end(),inserter(temp2,temp2.begin()));
            A=temp2;
            if(A.size()==0)return false;
            else if(A.find(node(target[0],target[1]))!=A.end())return true;
            if(B.find(node(target[0],target[1]))!=B.end())return false;
        }
    }
};

尬住了,简单的几个测试用例都通过了,但是提交时,有些用力超时了。虽然尝试做之前就估计这种笨笨的模拟会超时,难受。

知识小结:

  1. set容器 添加自定义的 数据类型时,要重载 < 且要声明const
  2. set求差集:set_difference()
  3. set求交集:set_intersection()
  4. set求并集:set_union()

正确思路: 曼哈顿距离

我写的比较蠢,想的是玩家在达到终点前是否会被抓到,这道题本身不需要更游戏一样展现出来,只要判断可能性即可,看了下别人的题解,既然都是一起行动的,只要玩家距离终点更近,就能跑掉,这个距离即曼哈顿距离。

自己简单写一下:

    bool escapeGhosts(vector<vector<int> >& ghosts, vector<int>& target) { 
        int p_dis=abs(target[0])+abs(target[1]);
        for(int i=0;i<ghosts.size();i++){
            int temp = abs(target[0]-ghosts[i][0])+abs(target[1]-ghosts[i][1]);
            if(temp<=p_dis)return false;
        }
        return true;
    }

尬住了,才这么点代码,有时候,思路真的很重要啊,不过模拟怪物抓玩家这个过程也蛮有意思的。

posted @ 2021-08-22 18:07  Beyond-189  阅读(36)  评论(0)    收藏  举报