1 条题解
-
0
题意分析
在 像素的网格路径上,若干辆坦克可沿每隔 10 像素的水平或垂直路径移动、转向或开火。给定每辆坦克的初始位置、朝向,以及按时间顺序到达的控制命令序列,模拟坦克和子弹的行为,直到所有命令执行完毕且战场上无子弹为止,输出最后存活的一辆坦克名称,否则则输出NO WINNER!。
解题思路
-
离散化路径:将坐标 对应为离散格点 ,移动速度 像素/秒 即每秒走 1 格;子弹速度 20 像素/秒 即每秒走 2 格。
-
时间效果实现:以最小时间单位 秒或直接按整数秒再细分命令与运动可混合处理,但推荐将时间戳和格数都离散化为一份进行,需要循环从 开始,进行以下步骤:
- 子弹更新:先移动所有存活子弹,并检测是否击中坦克或出界;
- 坦克命令:执行所有在当前时刻到达的命令(MOVE/STOP/TURN/SHOOT);
- 坦克移动:移动所有标记为存活的坦克;
- 终止检测:当所有命令已处理且无子弹存活时结束。
-
存活状态判定:坦克和子弹都进行标记;坦克被击中瞬间置为死并移出映射,同时子弹击中或出界后置为死。结束后统计存活坦克数,若恰为 1 则输出其名字,反之则输出 NO WINNER!。
本题代码
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; const int MAXN = 10; const int MAXM = 1000; const int GRID = 13; // 0..12 共 13 格 const int MAXB = 1005; // 最多子弹数 struct Tank { string name; int x, y; // 0..12 格 int dir; // 0=右,90=上,180=左,270=下 bool moving; bool alive; } tanks[MAXN]; struct Bullet { int x, y; int dir; bool alive; } bullets[MAXB]; struct Cmd { int time; // 离散时间,单位:格/秒 string name; string type; int angle; // TURN 时的角度,否则忽略 } cmds[MAXM]; int tankMap[GRID][GRID]; int bulletMap[GRID][GRID]; int dx[4] = {1, 0, -1, 0}; // dir=0,90,180,270 对应索引 0,1,2,3 int dy[4] = {0, 1, 0, -1}; int dirIndex(int d) { if (d == 0) return 0; if (d == 90) return 1; if (d == 180) return 2; return 3; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, M; while (cin >> N >> M) { if (N==0 && M==0) break; // 初始化 memset(tankMap, -1, sizeof(tankMap)); for (int i = 0; i < N; i++) { tanks[i].alive = true; tanks[i].moving = false; cin >> tanks[i].name; int px, py; cin >> px >> py >> tanks[i].dir; tanks[i].x = px / 10; tanks[i].y = py / 10; tankMap[tanks[i].x][tanks[i].y] = i; } // 读命令,时间离散化:每秒6格 -> *6 for (int i = 0; i < M; i++) { cin >> cmds[i].time >> cmds[i].name >> cmds[i].type; if (cmds[i].type == "TURN") cin >> cmds[i].angle; cmds[i].time *= 6; } // 模拟 memset(bulletMap, -1, sizeof(bulletMap)); for (int i = 0; i < MAXB; i++) bullets[i].alive = false; int bulletCnt = 0, cmdPtr = 0; // 时间上限:命令最后时刻 + 额外子弹飞行时间 int t = 0; while (true) { // 清空子弹映射,重建 memset(bulletMap, -1, sizeof(bulletMap)); for (int i = 0; i < bulletCnt; i++) if (bullets[i].alive) bulletMap[bullets[i].x][bullets[i].y] = i; // 子弹击中检测 for (int i = 0; i < bulletCnt; i++) { if (!bullets[i].alive) continue; int bx = bullets[i].x, by = bullets[i].y; if (tankMap[bx][by] != -1) { int ti = tankMap[bx][by]; tanks[ti].alive = false; tankMap[bx][by] = -1; bullets[i].alive = false; } } // 执行当前时刻命令 while (cmdPtr < M && cmds[cmdPtr].time == t) { for (int i = 0; i < N; i++) if (tanks[i].alive && tanks[i].name == cmds[cmdPtr].name) { auto &tk = tanks[i]; if (cmds[cmdPtr].type == "MOVE") tk.moving = true; else if (cmds[cmdPtr].type == "STOP") tk.moving = false; else if (cmds[cmdPtr].type == "TURN") tk.dir = (tk.dir + cmds[cmdPtr].angle + 360) % 360; else if (cmds[cmdPtr].type == "SHOOT") { bullets[bulletCnt] = {tk.x, tk.y, tk.dir, true}; bulletCnt++; } break; } cmdPtr++; } // 子弹移动 for (int i = 0; i < bulletCnt; i++) { if (!bullets[i].alive) continue; int idx = dirIndex(bullets[i].dir); int nx = bullets[i].x + 2*dx[idx]; int ny = bullets[i].y + 2*dy[idx]; if (nx<0 || nx>=GRID || ny<0 || ny>=GRID) { bullets[i].alive = false; } else { bullets[i].x = nx; bullets[i].y = ny; } } // 坦克移动 for (int i = 0; i < N; i++) { if (!tanks[i].alive || !tanks[i].moving) continue; auto &tk = tanks[i]; tankMap[tk.x][tk.y] = -1; int idx = dirIndex(tk.dir); int nx = tk.x + dx[idx]; int ny = tk.y + dy[idx]; if (nx<0||nx>=GRID||ny<0||ny>=GRID) { tk.moving = false; } else { tk.x = nx; tk.y = ny; } tankMap[tk.x][tk.y] = i; } // 终止条件:命令已执行完且无子弹存活 bool bulletsAlive = false; for (int i = 0; i < bulletCnt; i++) if (bullets[i].alive) { bulletsAlive = true; break; } if (cmdPtr==M && !bulletsAlive) break; t++; } // 输出结果 int aliveCnt = 0; string winner; for (int i = 0; i < N; i++) { if (tanks[i].alive) { aliveCnt++; winner = tanks[i].name; } } if (aliveCnt == 1) cout << winner << "\n"; else cout << "NO WINNER!\n"; } return 0; }
-
- 1
信息
- ID
- 1729
- 时间
- 2000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 15
- 已通过
- 1
- 上传者