西安葡萄城校招一面面试题(挺有意思)

前几天参加西安葡萄城的校招面试,发挥挺拉跨的,但没想到一面还是过了,当时面试官问了我一个面试题,感觉挺有意思的,在这记录一下,并手动实现。

问题:
给n个窗口的打开顺序,然后每个窗口的左上角顶点的坐标,和宽高,还有一个光标的坐标。问光标所在位置是哪个窗口,并且这个窗口的可视面积?(窗口与窗口之间重叠后,后打开的窗口会把先打开的窗口覆盖)

问题一找到光标在哪一个窗口?
思路:
根据给定的打开顺序,从后向前遍历,光标是否在当前窗口。

第二个问题求某个窗口的可视面积?
对某个窗口中的数据处理成矩形,用扫描线来做

代码:

//makefile
src = $(wildcard ./*.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
target = app
CC = g++  
$(target): $(obj)
	$(CC) $(obj) -o $(target)

%.o: %.cpp
	$(CC) -c $< -o $@
.PHONY: clean
clean:
	rm -rf $(obj) $(target)
#include <algorithm>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <vector>
#ifndef _VIEWARE_H_
#define _VIEWARE_H_
#define L INT_MIN
#define R INT_MAX
class Windows;
class Line;
class GetFillArea;
class Soultion;

class Windows {
 public:
  Windows() {}
  Windows(int windowsNums)
      : _windowsSize(windowsNums), _worldHeight(100), _worldWidth(100) {
    _worldIndex.first = _worldIndex.second = 0;
  }
  ~Windows() {}
  int _windowsSize;
  int _worldHeight;
  int _worldWidth;
  static std::vector<int> _coordinate;
  std::pair<int, int> _worldIndex;                 //世界坐标原点
  std::vector<std::vector<int>> _worldCoordinate;  //世界坐标点
  void setWindowsSize(int size) { this->_windowsSize = size; }
  void setWorldHeight(int heigth) { this->_worldHeight = heigth; }
  void setWorldWidth(int width) { this->_worldWidth = width; }
  void insertCoordinate(int x, int y, int width, int height);
  int findWindows(int x, int y);
  void buildPartialData(int windowsIndex);  //构造局部矩形内的数据
  void prPartia();
  std::vector<std::vector<int>> _partiaMatrix;
};

class Line {
 public:
  Line(int sx, int sty, int sdy, bool sfla)
      : x(sx), ty(sty), dy(sdy), fla(sfla) {}
  int x, ty, dy;
  bool fla;
  bool operator<(const Line& a) { return x < a.x; }
};

class GetFillArea {
 public:
  GetFillArea() {}
  std::unordered_map<int, int> Len, Lazy, Rson, Lson;
  std::vector<Line> line;
  std::vector<int> _axis;
  void prepareData(std::vector<std::vector<int>>& matrix);
  void buildTree(int k, int Ls, int Rs);
  void updateInterval(int k, int l, int r, int w);
  void pushUp(int k);
  int getFillArea();
  bool isfill = false;
};

class Soultion {
 public:
  Soultion(){};
  int getViewArea(std::vector<std::vector<int>>& Matrix,int x,int y);
};
#endif
#include "Viewarea.h"
std::vector<int> Windows::_coordinate(4, 0);

void Windows::insertCoordinate(int x, int y, int width, int height) {
  this->_coordinate[0] = x;
  this->_coordinate[1] = y;
  this->_coordinate[2] = x + width;
  this->_coordinate[3] = y + height;
  this->_worldCoordinate.push_back(_coordinate);
}

int Windows::findWindows(int x, int y) {
  int Index = -1;
  for (int i = this->_worldCoordinate.size() - 1; i >= 0; i--) {
    if (x >= _worldCoordinate[i][0] && y >= _worldCoordinate[i][1] &&
        x <= _worldCoordinate[i][2] && y <= _worldCoordinate[i][3]) {
      return i;
    }
  }
  return Index;
}

void Windows::buildPartialData(int windowsindex) {
  int _ax = this->_worldCoordinate[windowsindex][0];
  int _ay = this->_worldCoordinate[windowsindex][1];

  int _dx = this->_worldCoordinate[windowsindex][2];
  int _dy = this->_worldCoordinate[windowsindex][3];

  int _bx = _dx;
  int _by = _ay;

  int _cx = _ax;
  int _cy = _dy;

  for (int i = windowsindex + 1; i < this->_worldCoordinate.size(); i++) {
    int ax = this->_worldCoordinate[i][0];
    int ay = this->_worldCoordinate[i][1];

    int dx = this->_worldCoordinate[i][2];
    int dy = this->_worldCoordinate[i][3];

    int bx = dx;
    int by = ay;

    int cx = ax;
    int cy = dy;

    bool isA, isB, isC, isD;
    int vertex = 0;
    isA = isB = isC = isD = false;
    if (ax >= _ax && ay >= _ay && ax <= _dx && ay <= _dy) {
      isA = true;
      vertex++;
    }

    if (bx >= _ax && by >= _ay && bx <= _dx && by <= _dy) {
      isB = true;
      vertex++;
    }

    if (cx >= _ax && cy >= _ay && cx <= _dx && cy <= _dy) {
      isC = true;
      vertex++;
    }

    if (dx >= _ax && dy >= _ay && dx <= _dx && dy <= _dy) {
      isD = true;
      vertex++;
    }

    if (!vertex) {
      continue;
    } else if (vertex == 1) {
      if (isA) {
        this->_coordinate[0] = ax;
        this->_coordinate[1] = ay;
        this->_coordinate[2] = _dx;
        this->_coordinate[3] = _dy;
      } else if (isB) {
        this->_coordinate[0] = _cx;
        this->_coordinate[1] = by;
        this->_coordinate[2] = bx;
        this->_coordinate[3] = _cy;
      } else if (isC) {
        this->_coordinate[0] = cx;
        this->_coordinate[1] = _by;
        this->_coordinate[2] = _bx;
        this->_coordinate[3] = cy;
      } else if (isD) {
        this->_coordinate[0] = _ax;
        this->_coordinate[1] = _ay;
        this->_coordinate[2] = dx;
        this->_coordinate[3] = dy;
      }
      this->_partiaMatrix.push_back(this->_coordinate);
    } else if (vertex == 2) {
      if (isA && isB) {
        this->_coordinate[0] = ax;
        this->_coordinate[1] = ay;
        this->_coordinate[2] = bx;
        this->_coordinate[3] = std::min(dy, _dy);
      } else if (isC && isD) {
        this->_coordinate[0] = cx;
        this->_coordinate[1] = std::max(ay, _ay);
        this->_coordinate[2] = dx;
        this->_coordinate[3] = dy;
      } else if (isA && isC) {
        this->_coordinate[0] = ax;
        this->_coordinate[1] = ay;
        this->_coordinate[2] = std::min(dx, _dx);
        this->_coordinate[3] = cy;
      } else if (isB && isD) {
        this->_coordinate[0] = std::max(ax, _ax);
        this->_coordinate[1] = ay;
        this->_coordinate[2] = dx;
        this->_coordinate[3] = dy;
      } else {
        this->_coordinate[0] = ax;
        this->_coordinate[1] = ay;
        this->_coordinate[2] = dx;
        this->_coordinate[3] = dy;
      }
      this->_partiaMatrix.push_back(this->_coordinate);
    } else {
      this->_coordinate[0] = ax;
      this->_coordinate[1] = ay;
      this->_coordinate[2] = dx;
      this->_coordinate[3] = dy;
      this->_partiaMatrix.push_back(this->_coordinate);
    }
  }
}

void Windows::prPartia() {
  for (auto x : this->_partiaMatrix) {
    std::cout << x[0] << ' ' << x[1] << ' ' << x[2] << ' ' << x[3] << std::endl;
  }
}

void GetFillArea::prepareData(std::vector<std::vector<int>>& matrix) {
  for (auto& Matrix : matrix) {
    Line lf(Matrix[0], Matrix[1], Matrix[3], true);
    Line ls(Matrix[2], Matrix[1], Matrix[3], false);
    this->line.push_back(lf);
    this->line.push_back(ls);
    this->_axis.push_back(Matrix[1]);
    this->_axis.push_back(Matrix[3]);
  }
  if (matrix.empty()) {
    isfill = true;
    return;
  }
  sort(line.begin(), line.end());
  sort(_axis.begin(), _axis.end());

}

void GetFillArea::pushUp(int k) {
  if (Lazy[k]) {
    Len[k] = Rson[k] - Lson[k];
  } else {
    Len[k] = Len[k << 1] + Len[k << 1 | 1];
  }
}

void GetFillArea::buildTree(int k, int Ls, int Rs) {
  Lson[k] = _axis[Ls - 1], Rson[k] = _axis[Rs - 1];
  if (Rs - Ls <= 1) {
    return;
  }
  int MID = (Ls + Rs) >> 1;
  buildTree(k << 1, Ls, MID);
  buildTree(k << 1 | 1, MID, Rs);
}

void GetFillArea::updateInterval(int k, int l, int r, int w) {
  if (Lson[k] >= l && Rson[k] <= r) {
    Lazy[k] += w;
    pushUp(k);
    return;
  }

  if (Rson[k << 1] > l) {
    updateInterval(k << 1, l, r, w);
  }

  if (Lson[k << 1 | 1] < r) {
    updateInterval(k << 1 | 1, l, r, w);
  }

  pushUp(k);
}

int GetFillArea::getFillArea() {
  int fillareas = 0;

  if (isfill) {
    return fillareas;
  }

  buildTree(1, 1, _axis.size());
  for (int i = 0; i < this->line.size() - 1; i++) {
    int pw = line[i].fla ? 1 : -1;
    updateInterval(1, line[i].ty, line[i].dy, pw);
    fillareas += Len[1] * (line[i + 1].x - line[i].x);
  }
  return fillareas;
}

int Soultion::getViewArea(std::vector<std::vector<int>>& Matrix, int x, int y) {
  std::shared_ptr<Windows> windows = std::make_shared<Windows>(Matrix.size());
  std::shared_ptr<GetFillArea> getfill = std::make_shared<GetFillArea>();
  for (auto pos : Matrix) {
    windows->insertCoordinate(pos[0], pos[1], pos[2], pos[3]);
  }
  int _index = windows->findWindows(x, y);
  int allAreas = abs(windows->_worldCoordinate[_index][0] -
                     windows->_worldCoordinate[_index][2]) *
                 abs(windows->_worldCoordinate[_index][1] -
                     windows->_worldCoordinate[_index][3]);
  windows->buildPartialData(_index);
  getfill->prepareData(windows->_partiaMatrix);
  return allAreas - getfill->getFillArea();
}
#include <iostream>
#include <memory>

#include "Viewarea.h"

int main() {
  std::shared_ptr<Soultion> soultion = std::make_shared<Soultion>();
  /*测试数据*/
  std::vector<std::vector<int>> Matrix = {{1, 1, 3, 3}, {1, 1, 1, 1},
                                          {1, 3, 1, 2}, {3, 2, 2, 2},
                                          {4, 4, 2, 2}, {2, 2, 5, 5}};
  /*光标所在位置*/
  int gx, gy;
  gx = 4, gy = 1;

  std::cout << "ViewArea: " << soultion->getViewArea(Matrix, gx, gy) << std::endl;

  return 0;
}
上一篇:Geogebra指令


下一篇:【优化求解】模拟退火遗传实现带时间窗的车辆路径规划问题