Time limit: 3.000 seconds

## Background

Simulation is an important application area in computer science involving the development of computer models to provide insight into real-world events. There are many kinds of simulation including (and certainly not limited to) discrete event simulation and clock-driven simulation. Simulation often involves approximating observed behavior in order to develop a practical approach.

This problem involves the simulation of a simplistic pinball machine. In a pinball machine, a steel ball rolls around a surface, hitting various objects (bumpers) and accruing points until the ball "disappears" from the surface.

## The Problem

You are to write a program that simulates an idealized pinball machine. This machine has a flat surface that has some obstacles (bumpers and walls). The surface is modeled as an m × n grid with the origin in the lower-left corner. Each bumper occupies a grid point. The grid positions on the edge of the surface are walls. Balls are shot (appear) one at a time on the grid, with an initial position, direction, and lifetime. In this simulation, all positions are integral, and the ball's direction is one of: up, down, left, or right. The ball bounces around the grid, hitting bumpers (which accumulates points) and walls (which does not add any points). The number of points accumulated by hitting a given bumper is the value of that bumper. The speed of all balls is one grid space per timestep. A ball "hits" an obstacle during a timestep when it would otherwise move on top of the bumper or wall grid point. A hit causes the ball to "rebound" by turning right (clockwise) 90 degrees, without ever moving on top of the obstacle and without changing position (only the direction changes as a result of a rebound). Note that by this definition sliding along a wall does not constitute "hitting" that wall.

A ball's lifetime indicates how many time units the ball will live before disappearing from the surface. The ball uses one unit of lifetime for each grid step it moves. It also uses some units of lifetime for each bumper or wall that it hits. The lifetime used by a hit is the cost of that bumper or wall. As long as the ball has a positive lifetime when it hits a bumper, it obtains the full score for that bumper. Note that a ball with lifetime one will "die" during its next move and thus cannot obtain points for hitting a bumper during this last move. Once the lifetime is non-positive (less than or equal to zero), the ball disappears and the game continues with the next ball.

## The Input

Your program should simulate one game of pinball. There are several input lines that describe the game. The first line gives integers m and n, separated by a space. This describes a cartesian grid where 1 ≤ x ≤ m and 1 ≤ y ≤ n on which the game is "played". It will be the case that 2 < m < 51 and 2 < n < 51. The next line gives the integer cost for hitting a wall. The next line gives the number of bumpers, an integer p ≥ 0. The next p lines give the x position, y position, value, and cost, of each bumper, as four integers per line separated by space(s). The x and y positions of all bumpers will be in the range of the grid. The value and cost may be any integer (i.e., they may be negative; a negative cost adds lifetime to a ball that hits the bumper). The remaining lines of the file represent the balls. Each line represents one ball, and contains four integers separated by space(s): the initial x and y position of the ball, the direction of movement, and its lifetime. The position will be in range (and not on top of any bumper or wall). The direction will be one of four values: 0 for increasing x (right), 1 for increasing y (up), 2 for decreasing x (left), and 3 for decreasing y (down). The lifetime will be some positive integer.

## The Output

There should be one line of output for each ball giving an integer number of points accumulated by that ball in the same order as the balls appear in the input. After all of these lines, the total points for all balls should be printed.

## Sample Input

4 4

0

2

2 2 1 0

3 3 1 0

2 3 1 1

2 3 1 2

2 3 1 3

2 3 1 4

2 3 1 5

## Sample Output

0

0

1

2

2

5

## Analysis

分析

此题为模拟类型，必须认真读题，绝不能漏掉任何一个细节。

小球碰到障碍物（墙或弹板）时仅会转向而不会移动，但无论小球是否移动生命值都要减1，因为每1步都消耗了1个单位的时间，碰到障碍物所减少的生命值另计。小球在移入弹板位置（下一步将被弹回到原位置）前生命值必须为正，否则不能得到分值，因为在移入的这个过程中小球的生命结束了。小球不能停留在任何障碍物的位置上，一旦发生碰撞必须立即回到原位。假设桌面的尺寸为3×3，桌面上就不可能有弹板，因为除了一圈子的墙外只有一格可供小球发射。在这种情况下，小球不会得到任何分值，生命值会在不断的撞墙中消耗殆尽。题目中所给的坐标均是以1为起始值。

## Solution

解答

#include <iostream> using namespace std; struct POINT { int x; int y; }; //记录弹板信息的结构体 struct BUMPER { int nValue; int nCost; }; int main(void) { //用二维数组记录所有弹板的信息，不存在弹板的位置为空指针 BUMPER *pTable[52][52] = {0}, *pBumper; //按照题目指定的方向编号，设定移动偏移量 POINT ptSize, ptPos, aDir[4] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} }; int nWCost, nTotal = 0, nValue, nLife, nDir; //输入桌面尺寸、墙的消耗、弹板数量 for (cin >> ptSize.x >> ptSize.y >> nWCost >> nTotal; nTotal-- > 0; ) { //循环读入每个弹板的坐标、分值以及消耗，并存入数组 cin >> ptPos.x >> ptPos.y; pBumper = new BUMPER; cin >> pBumper->nValue >> pBumper->nCost; //弹板的坐标是以1起始的，需适配以0起始的数组地址 pTable[ptPos.x - 1][ptPos.y - 1] = pBumper; } //桌面尺寸也需适配以0起始的数组地址 ptSize.x -= 1, ptSize.y -= 1; //循环读入每个球的起始坐标，起始方向和生命值 for (nTotal = 0; cin >> ptPos.x >> ptPos.y >> nDir >> nLife;) { //使坐标适配数组地址 --ptPos.x, --ptPos.y; //循环移动小球，直到生命结束 for (nValue = 0; --nLife > 0; ) { //建立新坐标变量存储移动后的值，以便移动失败时回退 POINT ptNew = {ptPos.x + aDir[nDir].x, ptPos.y + aDir[nDir].y}; //撞墙 if (ptNew.x == ptSize.x || ptNew.y == ptSize.y || ptNew.x < 1 || ptNew.y < 1) { //生命值减去墙的消耗并转向 nLife -= nWCost; nDir = (nDir + 3) % 4; continue; } //碰到弹板 if ((pBumper = pTable[ptNew.x][ptNew.y]) != 0) { //分值加上弹板的分值，生命值减去消耗并转向 nValue += pBumper->nValue; nLife -= pBumper->nCost; nDir = (nDir + 3) % 4; continue; } //移动到空白格子 ptPos = ptNew; } //总分累加这一次的分值并输出当前分值 nTotal += nValue; cout << nValue << endl; } //输出总分，程序结束 cout << nTotal << endl; return 0; }