题解:UVA114 Simulation Wizardry
UVA114
一道十分烦的模拟题
题意简述
模拟一盘弹珠游戏,游戏在一个 的网格中进行。最外面一圈是墙,里面某些位置有 bumper。弹珠从某位置以某方向射入,撞到墙或 bumper 后,方向会顺时针转 。
弹珠有一个 life 值,每次移动一格消耗 点 life。墙和每个 bumper 各有一个伤害值,每次弹珠撞到它们会被扣除相应的 life。其中 bumper 还有一个奖励值,弹珠撞到 bumper 后会得到相应的分数。弹珠 life 小于等于 时,游戏结束。
输出每个弹珠的得分,以及所有弹珠的得分之和。
其他细节详见英文题面。
解题思路
题目本身较难读懂,现列出一些坑点:
- 弹珠撞到障碍物后,会消耗 点 life 在原地顺时针转 ,也就是说在下一时刻内只旋转不运动;
- 墙和 bumper 的伤害值可以小于 ,此时会给弹珠补血;
- 墙也在网格内,也就是说弹珠最大活动范围为 。
样例的初始状态: 
运动过程: 
不得不说这样例也挺令人无语的
另一个样例:
Input:
7 3
-3
2
2 2 2 2
6 2 -3 0
4 2 3 7
Output:
1
1运动过程:
============
Life: 7
Tot: 0
#######
#*.v.*#
#######
Life: 9
Tot: 0
#######
#*.<.*#
#######
Life: 8
Tot: 0
#######
#*<..*#
#######
Life: 5
Tot: 2
#######
#*^..*#
#######
Life: 7
Tot: 2
#######
#*>..*#
#######
Life: 6
Tot: 2
#######
#*.>.*#
#######
Life: 5
Tot: 2
#######
#*..>*#
#######
Life: 4
Tot: -1
#######
#*..v*#
#######
Life: 6
Tot: -1
#######
#*..<*#
#######
Life: 5
Tot: -1
#######
#*.<.*#
#######
Life: 4
Tot: -1
#######
#*<..*#
#######
Life: 1
Tot: 1
#######
#*^..*#
#######
1
============思路理清后便可以写了,可以使用一些 trick 方便写代码:
- 使用
move函数使弹珠向现在的方向运动一格,并建立数组back记录每个方向的反方向。这样可以先move,如果撞到障碍物则可以将方向掉头,再move一下回到原来位置,再掉头回到原来方向。这样总共消耗 点 life。 - 建立数组
turn记录每个方向转 后的方向。
代码
#include<iostream>
#ifdef ONLINE_JUDGE
#define getchar getchar_unlocked
#endif
using namespace std;
/*================*/
inline int read() {
char c=getchar();int x=0,f=1;
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return x*f;
}
#define r(a) (a)=read()
int n,m;
int cost[55][55];
int val[55][55];
bool obs[55][55]; //是否是障碍物
int wallcost,p;
int x,y,dir,life;
int tot,acc;
int turn[]={3,0,1,2};
int back[]={2,3,0,1};
void move() {
if (dir==0)
x++;
else if (dir==1)
y++;
else if (dir==2)
x--;
else
y--;
}
bool hitwall(int x,int y) {
return x==1 || x==m || y==1 || y==n;
}
bool hitbumper(int x,int y) {
return obs[x][y];
}
signed main() {
r(m); r(n);
r(wallcost); r(p);
while (p--) {
r(x); r(y);
val[x][y]=read();
cost[x][y]=read();
obs[x][y]=1;
}
while (scanf("%d%d%d%d",&x,&y,&dir,&life)==4) {
tot=0;
while (life>0) {
move();
life--;
if (life<=0) break;
if (hitwall(x,y)) { //撞到墙
life-=wallcost;
dir=back[dir];
move(); //转回来
dir=back[dir];
dir=turn[dir];
}
else if (hitbumper(x,y)) { //撞到 bumper
life-=cost[x][y];
tot+=val[x][y];
dir=back[dir];
move(); //转回来
dir=back[dir];
dir=turn[dir];
}
}
printf("%d\n",tot);
acc+=tot;
}
printf("%d\n",acc);
return 0;
}题解:UVA114 Simulation Wizardry
https://pvbelln.github.io/2025/07/15/sol-uva114/