STL的妙用(一)——洛谷 P1189 `SEARCH`

题目链接

题目描述

年轻的拉尔夫开玩笑地从一个小镇上偷走了一辆车,但他没想到的是那辆车属于警察局,并且车上装有用于发射车子移动路线的装置。

那个装置太旧了,以至于只能发射关于那辆车的移动路线的方向信息。

编写程序,通过使用一张小镇的地图帮助警察局找到那辆车。程序必须能表示出该车最终所有可能的位置。

小镇的地图是矩形的,上面的符号用来标明哪儿可以行车哪儿不行。“.”表示小镇上那块地方是可以行车的,而符号“X”表示此处不能行车。拉尔夫所开小车的初始位置用字符的“*”表示,且汽车能从初始位置通过。

汽车能向四个方向移动:向北(向上),向南(向下),向西(向左),向东(向右)。

拉尔夫所开小车的行动路线是通过一组给定的方向来描述的。在每个给定的方向,拉尔夫驾驶小车通过小镇上一个或更多的可行车地点。

思路

直接上代码(第一版):

#include <bits/stdc++.h>
using namespace std;
int r, c;
char mp[51][51];
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
struct node
{
  int x, y;
  node(int x, int y) : x(x), y (y) {}
};
int main() {
  cin >> r >> c;
  int sx, sy;
  vector<node> ths;
  vector<node> nxt;
  for (int i = 1; i <= r; ++i) {
    for (int j = 1; j <= c; ++j) {
      cin >> mp[i][j];
      if (mp[i][j] == '*')
      {
        nxt.push_back(node(i, j));
        mp[i][j] = '.';
      }
    }
  }
  int n;
  cin >> n;
  for (int i = 1; i <= n; ++i) {
    string s;
    cin >> s;
    int d;
    switch(s[0]) {
      case 'N':
        d = 0;
        break;
      case 'W':
        d = 1;
        break;
      case 'S':
        d = 2;
        break;
      case 'E':
        d = 3;
        break;
    }
    ths = nxt;
    nxt.clear();
    for (node i : ths) {
      int cx = i.x + dx[d], cy = i.y + dy[d];
      while (mp[cx][cy] == '.')
      {
        nxt.push_back(node(cx, cy));
        cx += dx[d];
        cy += dy[d];
      }
    }
  }
  for (node i : nxt)
    mp[i.x][i.y] = '*';
  for (int i = 1; i <= r; ++i) {
    for (int j = 1; j <= c; ++j)
      cout << mp[i][j];
    cout << endl;
  }
}

一句话描述:用一个vector维护所有可能的起点,然后枚举出所有可能的终点放在另一个vector里,最后把这些终点作为新的起点。

然后我兴奋地提交了上去

优化

原因很简单:vector里会有大量重复元素。例如,如果方向信息为:

NORTH
SOUTH
NORTH
SOUTH
NORTH
SOUTH
NORTH
SOUTH

这样反复横跳上几次,vector就被塞爆了(

那么怎么解决呢?🤔


常规的思路是额外维护一个bool数组,记录哪些点已经在vector里了,然后每次循环前清空。

但!是!我们有更好的做法!

#include <bits/stdc++.h>
using namespace std;
int r, c;
char mp[51][51];
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
struct node
{
  int x, y;
  node(int x, int y) : x(x), y (y) {}
};
bool operator<(node a, node b) {
  return a.x == b.x ? a.y < b.y : a.x < b.x;
}
int main() {
  cin >> r >> c;
  int sx, sy;
  set<node> ths;
  set<node> nxt;
  for (int i = 1; i <= r; ++i) {
    for (int j = 1; j <= c; ++j) {
      cin >> mp[i][j];
      if (mp[i][j] == '*')
      {
        nxt.insert(node(i, j));
        mp[i][j] = '.';
      }
    }
  }
  int n;
  cin >> n;
  for (int i = 1; i <= n; ++i) {
    string s;
    cin >> s;
    int d;
    switch(s[0]) {
      case 'N':
        d = 0;
        break;
      case 'W':
        d = 1;
        break;
      case 'S':
        d = 2;
        break;
      case 'E':
        d = 3;
        break;
    }
    ths = nxt;
    nxt.clear();
    for (node i : ths) {
      int cx = i.x + dx[d], cy = i.y + dy[d];
      while (mp[cx][cy] == '.')
      {
        nxt.insert(node(cx, cy));
        cx += dx[d];
        cy += dy[d];
      }
    }
  }
  for (node i : nxt)
    mp[i.x][i.y] = '*';
  for (int i = 1; i <= r; ++i) {
    for (int j = 1; j <= c; ++j)
      cout << mp[i][j];
    cout << endl;
  }
}

我们把vector改成了set!!!

也就是说现在我们不用担心重复了!

过了jaja

posted @ 2020-04-25 18:37  water_lift  阅读(158)  评论(0编辑  收藏  举报