题解:UVA114 Simulation Wizardry

UVA114

一道十分烦的模拟题

题意简述

模拟一盘弹珠游戏,游戏在一个 m×nm \times n 的网格中进行。最外面一圈是墙,里面某些位置有 bumper。弹珠从某位置以某方向射入,撞到墙或 bumper 后,方向会顺时针转 9090 ^ \circ

弹珠有一个 life 值,每次移动一格消耗 11 点 life。墙和每个 bumper 各有一个伤害值,每次弹珠撞到它们会被扣除相应的 life。其中 bumper 还有一个奖励值,弹珠撞到 bumper 后会得到相应的分数。弹珠 life 小于等于 00 时,游戏结束。

输出每个弹珠的得分,以及所有弹珠的得分之和。

其他细节详见英文题面。

解题思路

题目本身较难读懂,现列出一些坑点:

  1. 弹珠撞到障碍物后,会消耗 11 点 life 在原地顺时针转 9090 ^ \circ,也就是说在下一时刻内只旋转不运动;
  2. 墙和 bumper 的伤害值可以小于 00,此时会给弹珠补血;
  3. 墙也在网格内,也就是说弹珠最大活动范围为 (m2)×(n2)(m-2) \times (n-2)

样例的初始状态:

运动过程:

不得不说这样例也挺令人无语的

另一个样例:

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 一下回到原来位置,再掉头回到原来方向。这样总共消耗 11 点 life。
  • 建立数组 turn 记录每个方向转 9090 ^ \circ 后的方向。

代码

#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/
作者
PvbeLLN
发布于
2025年7月15日
许可协议