P4944
Time:23 ms,Memory:756.00 KB,Code:3.07KB
不加 O2,发此篇题解的时候是最优解 rk1。
题意
给出一个地图,地图上初始有 \(c\) 条贪吃蛇和一些食物。
接下来会给出 \(k\) 秒内每条贪吃蛇的移动规则,你需要输出 \(k\) 秒后所有蛇的信息。
分析&代码
写一个 Snake
类,来存放所有有关蛇的操作。
struct node { //结点
int x, y;
};
class Snake {
private:
std::deque<node> body; //蛇
void die(void) { //清除蛇身
live = false;
len = 0;
while (!body.empty()) {
node cac = body.front();
body.pop_front();
map[cac.x][cac.y] = '&', restFood++;
}
return;
}
public:
Snake(int x, int y, int id) { //BFS 寻找蛇身
this->id = id;
len = 0;
live = true;
static std::queue<node> que;
que.push((node){x, y});
while (!que.empty()) {
node cac = que.front();
vis[cac.x][cac.y] = true;
body.push_back(cac), len++;
que.pop();
for (int i = 0; i < 4; i++) {
int tx = cac.x + way[0][i], ty = cac.y + way[1][i];
if (tx >= 1 && tx <= n && ty >= 1 && ty <= m &&
!vis[tx][ty] && map[tx][ty] == '#') que.push((node){tx, ty});
}
}
return;
}
~Snake(void) {
body.clear();
return;
}
bool live;
int id, len;
void move(char way) {
node to = body.front();
map[to.x][to.y] = '#'; //删除蛇头
if (way == 'W') to.x--; //四个方向
if (way == 'S') to.x++;
if (way == 'A') to.y--;
if (way == 'D') to.y++;
if (to.x < 1 || to.x > n || to.y < 1 || to.y > m ||
map[to.x][to.y] == '#' || map[to.x][to.y] == '@') return die(); //如果撞到蛇身或者边界
body.push_front(to), len++;
if (map[to.x][to.y] == '&') return restFood--, void(map[to.x][to.y] = '@'); //吃食物
map[to.x][to.y] = '@';
map[body.back().x][body.back().y] = '.'; //删除尾部,增加新的头部
return len--, body.pop_back();
}
inline bool operator<(const Snake& oth) const {
return this->len > oth.len || this->len == oth.len && this->id < oth.id;
}
};
其中构造函数负责 BFS 初始化蛇身,move(char)
函数负责让蛇向指定方向移动。此时如果蛇死了会直接调用 die(void)
清除蛇身。
这里有一点巧的就是在蛇吃掉食物后,只要让食物变成新蛇头就可以了。
如果蛇没有吃掉食物,删除蛇尾并且在前方标记新头即可。
上面的类定义完之后,面向对象模拟题意即可。
int main() {
std::ios::sync_with_stdio(false);
int k, c;
std::cin >> n >> m >> k;
restFood = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
std::cin >> map[i][j];
if (map[i][j] == '&') restFood++;
}
c = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (map[i][j] == '@') snakes.push_back((Snake){i, j, ++c}); //通过蛇头直接初始化蛇身
for (int i = 0; i < c; i++)
for (int j = 1; j <= k; j++)
std::cin >> cmd[i][j];
for (int tim = 1; tim <= k; tim++)
for (int p = 0; p < c; p++) {
if (!snakes[p].live) continue;
snakes[p].move(cmd[p][tim]); //让蛇向指定方向移动一格
}
std::sort(snakes.begin(), snakes.end());
for (std::vector<Snake>::iterator i = snakes.begin(); i != snakes.end(); i++)
std::cout << i->len << ' ' << i->id << std::endl;
std::cout << restFood << std::endl;
return 0;
}