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