題目連接 :http://poj.org/problem?id=2729ios
題目很長,有很多也是廢話。相似小時候玩的坦克大戰。每一個坦克速度爲10,炮彈速度爲20.子彈出界就消失,坦克出不了界限。相向的子彈碰撞不會消失(區別與小時候的遊戲,炮彈能夠抵消)。 ide
坦克能夠90轉向...很多條件題目中仔細讀能夠知道。this
在這裏須要注意的是,因爲炮彈速度和坦克移動的速度不一致,致使對與一個時間單位,坦克與子彈在座標上的處理挺困難。由於若是子彈在最左小角,向右邊發射,坦克恰好在子彈右邊一個單位,而坦克正好向左邊運動,spa
那麼它們的碰撞點將會在一個距離單位的中間偏右2/3處,碰撞時間爲1/3個單位時間;還有。若是坦克不動,則碰撞時間爲1/2;所以咱們取兩者最大公約數1/6爲時間單位。這樣處理適合碰撞時間和地點。code
所以,120的長度將擴大爲720,至關於原來的每一格變成了6小格。坦克每6個時間單位走6格,即原來的一個時間單位走一格。blog
1 #include <iostream> 2 #include <fstream> 3 #include <string> 4 #include <vector> 5 using namespace std; 6 7 struct Spirit // 坦克和子彈都從這個類派生 8 { 9 int x, y; // 位置 10 int face; // 前進方向 11 }; 12 struct Bullet : public Spirit // 子彈類 13 { 14 15 }; 16 struct Tank : public Spirit // 坦克類 17 { 18 string name; // 坦克名稱 19 bool move; // 標記坦克是移動仍是靜止 20 Bullet CreateBullet(); // 坦克發射一枚子彈 21 }; 22 Bullet Tank::CreateBullet() // 坦克發射一枚子彈,剛發射的時候子彈的位置和前進方向和坦克是同樣的 23 { 24 Bullet b; 25 b.x = x; 26 b.y = y; 27 b.face = face; 28 return b; 29 } 30 31 struct Command // 命令類 32 { 33 int time; // 執行時刻 34 string name; // 相應的坦克 35 string type; // 命令類型 36 int angle; // 若是是轉向,標記轉了多少度 37 }; 38 39 class Robocode // 解題類 40 { 41 protected: 42 const int h; // 地圖高度(離散化以後) 43 const int w; // 地圖寬度(離散化以後) 44 int n; // 坦克數量 45 int m; // 指令數量 46 vector<Tank> tanks; // 坦克集合向量 47 vector<Bullet> bullets; // 子彈集合向量 48 vector<Command> commands; // 命令集合向量 49 int** tankmap; // tankmap[i][j]表示第i行第j列的坦克在對應的向量中的下標,若是是-1則表示第i行第j列沒有坦克 50 int** bulletmap; // bulletmap[i][j]表示第i行第j列有沒有子彈,如是是1表示第i行第j列有子彈,若是是-1則表示第i行第j列沒有子彈 51 // void InitBullet(); 52 void Explode(); // 檢查子彈會不會擊中坦克,以及擊中後的處理 53 void ExcuteCmd(const Command& cmd); // 執行命令cmd 54 void UpdateBullet(); // 更新子彈集合在某一時刻的位置信息 55 void UpdateTank(); // 更新坦克集合在某一時刻的位置信息 56 public: 57 Robocode(int n, int m, const vector<Tank>& tanks, const vector<Command>& commands); // 構造方法 58 ~Robocode(); // 析構方法 59 void Run(); // 模擬過程 60 void Output() const; //輸出結果 61 }; 62 63 Robocode::Robocode(int n, int m, const vector<Tank>& tanks, const vector<Command>& commands) 64 :h(12 * 6 + 1), w(12 * 6 + 1) // 注意高度和寬度作離散化處理,要乘上6(想一想爲何) 65 { 66 this->n = n; 67 this->m = m; 68 this->tanks.reserve(n); 69 this->commands.reserve(m); 70 tankmap = new int*[h]; 71 for (int i = 0; i < h; i++) 72 { 73 tankmap[i] = new int[w]; 74 } 75 bulletmap = new int*[h]; 76 for (int i = 0; i < h; i++) 77 { 78 bulletmap[i] = new int[w]; 79 } 80 this->tanks.assign(tanks.begin(), tanks.end()); 81 this->commands.assign(commands.begin(), commands.end()); 82 for (int i = 0; i < h; i++) 83 { 84 for (int j = 0; j < w; j++) 85 { 86 tankmap[i][j] = -1; 87 } 88 } 89 for (int i = 0; i < h; i++) 90 { 91 for (int j = 0; j < w; j++) 92 { 93 bulletmap[i][j] = -1; 94 } 95 } 96 // 對坦克的位置信息進行離散化處理 97 for (unsigned int i = 0; i < this->tanks.size(); i++) 98 { 99 this->tanks[i].x = (this->tanks[i].x / 10) * 6; 100 this->tanks[i].y = (this->tanks[i].y / 10) * 6; 101 this->tanks[i].move = false; 102 tankmap[this->tanks[i].x][this->tanks[i].y] = i; 103 } 104 // 對時間進行離散化處理 105 for (unsigned int i = 0; i < this->commands.size(); i++) 106 { 107 this->commands[i].time *= 6; 108 } 109 } 110 Robocode::~Robocode() 111 { 112 for (int i = 0; i < h; i++) 113 { 114 delete[] tankmap[i]; 115 } 116 delete[] tankmap; 117 for (int i = 0; i < h; i++) 118 { 119 delete[] bulletmap[i]; 120 } 121 delete[] bulletmap; 122 } 123 //void Robocode::InitBullet() 124 //{ 125 // for (int i = 0; i < h; i++) 126 // { 127 // for (int j = 0; j < w; j++) 128 // { 129 // bulletmap[i][j] = -1; 130 // } 131 // } 132 // for (unsigned int i = 0; i < bullets.size(); i++) 133 // { 134 // bulletmap[bullets[i].x][bullets[i].y] = 1; 135 // } 136 //} 137 138 // 判斷有沒有出現子彈打中坦克的狀況,若是出現,進行處理 139 void Robocode::Explode() 140 { 141 for (int i = 0; i < h; i++) 142 { 143 for (int j = 0; j < w; j++) 144 { 145 if (bulletmap[i][j] > -1 && tankmap[i][j] > -1) //離散化後的第i行第j列發生了子彈和坦克碰撞 146 { 147 for (unsigned int k = 0; k < bullets.size();) // 遍歷子彈,注意for語句的表達式3空缺,不可直接寫k++ 148 { 149 if (bullets[k].x == i && bullets[k].y == j) // 注意這裏若是多個子彈和一輛坦克碰撞,都通通消失 150 { 151 bullets.erase(bullets.begin() + k); // 刪除對應的子彈 152 } 153 else 154 { 155 k++; 156 } 157 } 158 bulletmap[i][j] = -1; // 標記離散化後的第i行第j列已經沒有子彈 159 for (unsigned int k = 0; k < tanks.size();) // 遍歷坦克,注意for語句的表達式3空缺,不可直接寫k++ 160 { 161 if (tanks[k].x == i && tanks[k].y == j) // 注意這裏若是多輛坦克和一個子彈碰撞,都通通消失 162 { 163 tanks.erase(tanks.begin() + k); // 刪除對應的坦克 164 } 165 else 166 { 167 k++; 168 } 169 } 170 tankmap[i][j] = -1; // 標記離散化後的第i行第j列已經沒有坦克 171 } 172 } 173 } 174 } 175 176 // 執行命令cmd 177 void Robocode::ExcuteCmd(const Command& cmd) 178 { 179 for (unsigned int i = 0; i < tanks.size(); i++) 180 { 181 if (cmd.name == tanks[i].name) 182 { 183 if (cmd.type == "MOVE") // 坦克移動,設置相應標誌便可 184 { 185 tanks[i].move = true; 186 } 187 else if (cmd.type == "STOP") // 坦克中止,設置相應標誌便可 188 { 189 tanks[i].move = false; 190 } 191 else if (cmd.type == "TURN") // 坦克轉向處理,注意取模 192 { 193 tanks[i].face = (tanks[i].face + cmd.angle + 360) % 360; 194 } 195 else if (cmd.type == "SHOOT") // 大炮開兮轟他娘(張宗昌) 196 { 197 Bullet b = tanks[i].CreateBullet(); // 坦克產生子彈 198 bullets.push_back(b); // 更新子彈向量 199 bulletmap[b.x][b.y] = bullets.size() - 1; // 標記對應的行列位置有子彈,設置子彈的下標 200 } 201 } 202 } 203 } 204 205 // 更新離散化後的某個時刻的子彈的位置信息 206 void Robocode::UpdateBullet() 207 { 208 for (unsigned int i = 0; i < bullets.size(); ) 209 { 210 // 反正子彈在消失之前老是飛的,因此上一時刻子彈i出現的位置和這一時刻子彈i出現的位置一定不同,先把原先位置標記沒有子彈 211 bulletmap[bullets[i].x][bullets[i].y] = -1; 212 switch (bullets[i].face) // 根據子彈的前進方向判斷子彈在這一時刻的位置 213 { 214 case 0: 215 bullets[i].x += 2; // 注意離散化後,子彈每次移動2個單位 216 if (bullets[i].x > w - 1) // 子彈向右飛出了區域,應從戰場消失 217 { 218 bullets.erase(bullets.begin() + i); 219 } 220 else 221 { 222 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向右到了下一個位置,更新相應的信息 223 i++; 224 } 225 break; 226 case 90: 227 bullets[i].y += 2; // 注意離散化後,子彈每次移動2個單位 228 if (bullets[i].y > h - 1) // 子彈向下飛出了區域,應從戰場消失 229 { 230 bullets.erase(bullets.begin() + i); 231 } 232 else 233 { 234 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向下到了下一個位置,更新相應的信息 235 i++; 236 } 237 break; 238 case 180: 239 bullets[i].x -= 2; // 注意離散化後,子彈每次移動2個單位 240 if (bullets[i].x < 0) // 子彈向左飛出了區域,應從戰場消失 241 { 242 bullets.erase(bullets.begin() + i); 243 } 244 else 245 { 246 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向左到了下一個位置,更新相應的信息 247 i++; 248 } 249 break; 250 case 270: 251 bullets[i].y -= 2; // 注意離散化後,子彈每次移動2個單位 252 if (bullets[i].y < 0) // 子彈向上飛出了區域,應從戰場消失 253 { 254 bullets.erase(bullets.begin() + i); 255 } 256 else 257 { 258 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向上到了下一個位置,更新相應的信息 259 i++; 260 } 261 break; 262 } 263 } 264 //InitBullet(); 265 } 266 267 // 更新某一時刻的坦克的位置信息 268 void Robocode::UpdateTank() 269 { 270 for (unsigned int i = 0; i < tanks.size(); i++) 271 { 272 if (tanks[i].move) // 只處理在移動的坦克,有的坦克是靜止的,不用處理 273 { 274 tankmap[tanks[i].x][tanks[i].y] = -1; // 移動的坦克確定不在原先的位置了 275 switch (tanks[i].face) // 根據坦克的前進方向判斷坦克在這一時刻的位置 276 { 277 case 0: // 向右前進 278 tanks[i].x += 1; // 注意離散化後,坦克每次移動1個單位 279 if (tanks[i].x > w - 1) // 若是到達最右邊的邊界 280 { 281 tanks[i].x = w - 1; // 不能穿越也不能消失,在右邊界原地不動 282 } 283 break; 284 case 90: // 向下前進 285 tanks[i].y += 1; // 注意離散化後,坦克每次移動1個單位 286 if (tanks[i].y > h - 1) // 若是到達最下邊的邊界 287 { 288 tanks[i].y = h - 1; // 不能穿越也不能消失,在下邊界原地不動 289 } 290 break; 291 case 180: 292 tanks[i].x -= 1; // 注意離散化後,坦克每次移動1個單位 293 if (tanks[i].x < 0) // 若是到達最左邊的邊界 294 { 295 tanks[i].x = 0; // 不能穿越也不能消失,在左邊界原地不動 296 } 297 break; 298 case 270: 299 tanks[i].y -= 1; // 注意離散化後,坦克每次移動1個單位 300 if (tanks[i].y < 0) // 若是到達最上邊的邊界 301 { 302 tanks[i].y = 0; // 不能穿越也不能消失,在上邊界原地不動 303 } 304 break; 305 } 306 tankmap[tanks[i].x][tanks[i].y] = i; // 在新位置標記坦克在坦克向量中的下標 307 } 308 } 309 } 310 void Robocode::Run() 311 { 312 unsigned int cmdidx = 0; 313 int time = 0; 314 bullets.clear(); 315 for (int i = 0; i < h; i++) 316 { 317 for (int j = 0; j < w; j++) 318 { 319 bulletmap[i][j] = -1; 320 } 321 } 322 while (true) 323 { 324 //InitBullet(); 325 Explode(); // 先處理這一時刻有沒有子彈擊中坦克的狀況,why? 326 327 //遍歷命令向量,若是某個向量的執行時刻到了,就執行 328 while (cmdidx < commands.size() && commands[cmdidx].time == time) 329 { 330 ExcuteCmd(commands[cmdidx]); 331 cmdidx++; 332 } 333 334 UpdateBullet(); // 更新子彈位置信息 335 UpdateTank(); // 更新坦克位置信息 336 //Explode(); 337 if (cmdidx >= commands.size()) //命令所有執行完了 338 { 339 if (bullets.size() > 0) // 讓子彈再飛一會(姜文《讓子彈飛》) 340 { 341 342 } 343 else // 若是命令所有執行完了,子彈也飛完了,說明遊戲結束 344 { 345 break; 346 } 347 } 348 time++; // 時間單位計數器加1 349 } 350 } 351 352 void Robocode::Output() const 353 { 354 if (tanks.size() == 1) 355 { 356 cout << tanks[0].name << "\n"; 357 } 358 else 359 { 360 cout << "NO WINNER!\n"; 361 } 362 } 363 364 int main() 365 { 366 //ifstream cin("Text.txt"); 367 int n = 0; 368 int m = 0; 369 cin >> n >> m; 370 while (n > 0 && m > 0) 371 { 372 vector<Tank> tanks; 373 vector<Command> commands; 374 for (int i = 0; i < n; i++) 375 { 376 Tank t; 377 cin >> t.name >> t.x >> t.y >> t.face; 378 tanks.push_back(t); 379 } 380 for (int i = 0; i < m; i++) 381 { 382 Command c; 383 cin >> c.time >> c.name >> c.type; 384 if (c.type == "TURN") 385 { 386 cin >> c.angle; 387 } 388 commands.push_back(c); 389 } 390 Robocode obj(n, m, tanks, commands); 391 obj.Run(); 392 obj.Output(); 393 cin >> n >> m; 394 } 395 return 0; 396 }