USACO2020DEC第三题(Stuck in a Rut)题解

题目
题目描述
Farmer John 最近扩大了他的农场,从奶牛们的角度看来这个农场相当于是无限大了!奶牛们将农场上放牧的区域想作是一个由正方形方格组成的无限大二维方阵,每个方格中均有美味的草(将每个方格看作是棋盘上的一个方格)。Farmer John 的 N 头奶牛(1≤N≤50)初始时位于不同的方格中,一部分朝向北面,一部分朝向东面。
每一小时,每头奶牛会执行以下二者之一:
如果她当前所在的方格里的草已经被其他奶牛吃掉了,则她会停下。
吃完她当前所在的方格中的所有草,并向她朝向的方向移动一个方格。
经过一段时间,每头奶牛的身后会留下一条被啃秃了的轨迹。
如果两头奶牛在一次移动中移动到了同一个有草的方格,她们会分享这个方格中的草,并在下一个小时继续沿她们朝向的方向移动。
请求出每头奶牛吃到的草的数量。有些奶牛永远不会停下,从而吃到无限多的草。
输入
输入的第一行包含 N。以下 N 行,每行描述一头奶牛的起始位置,包含一个字符 N(表示朝向北面) 或 E(表示朝向东面),以及两个非负整数 x 和 y(0≤x≤109,0≤y≤109)表示方格的坐标。所有 x 坐标各不相同,所有 y 坐标各不相同。
为了使方向和坐标尽可能明确,如果一头奶牛位于方格 (x,y) 并向北移动,她会到达方格 (x,y+1)。如果她向东移动,她会到达方格 (x+1,y)。
输出
输出 N 行。输出的第 i 行包含输入中的第 i 头奶牛吃到草的方格的数量。如果一头奶牛可以吃到无限多的草,为这头奶牛输出 “Infinity”。
样例输入
6
E 3 5
N 5 3
E 4 6
E 10 4
N 11 2
N 8 1
样例输出
5
3
Infinity
Infinity
2
8
5
解题思路
按照题意模拟。每次取出堆顶将堆顶的牛子朝它的方向前进一格,并判断前进后的牛是否被阻碍,若当前的牛被阻碍,记录下这头牛是被谁阻碍的。计算牛前进的下一格的坐标,若超出地图范围则不把这个牛放回里(即永远不会被阻碍)。否则,计算前进到下一格所需要的时间,加上当前时间后塞回里。
参考代码

#include
using namespace std;
const int N = 105, inf = 0x3f3f3f3f;
typedef long long ll;
struct node {
     
	int stop, x, y; char opt;
} a[N];
int n, tmp[N];
int hit(int x, int y, int now) {
     
	node i = a[x], j = a[y];
	if (i.opt == j.opt) {
     
		return inf;
	}
	if (i.opt == 'E') {
     
		swap(i.x, i.y); swap(j.x, j.y);
	}
	if (j.y <= i.y) {
     
		return inf;
	}
	if (j.stop == inf) {
     
		if (i.x < j.x - now || i.x >= j.x + j.y - i.y) {
     
			return inf;
		}
	} else {
     
		if (i.x > j.x || i.x < j.x - j.stop) {
     
			return inf;
		}
	}
	return now + j.y - i.y;
}
int move(int now) {
     
	int minn = inf; memset(tmp, 0, sizeof tmp);
	for (int i = 1; i <= n; ++i) {
     
		tmp[i] = inf;
		if (a[i].stop == inf) {
     
			for (int j = 1; j <= n; ++j) {
     
				tmp[i] = min(tmp[i], hit(i, j, now));
			}
			minn = min(minn, tmp[i]);
		}
	}
	if (minn == inf) {
     
		return inf;
	}
	for (int i = 1; i <= n; ++i) {
     
		if (a[i].stop == inf) {
     
			if (a[i].opt == 'N') {
     
				a[i].y += (minn - now);
			} else {
     
				a[i].x += (minn - now);
			}
		}
		if (tmp[i] == minn)	{
     
			a[i].stop = minn;
		}
	}
	return minn;
}
int main() {
     
	cin >> n;
	for (int i = 1; i <= n; ++i) {
     
		cin >> a[i].opt >> a[i].x >> a[i].y;
		a[i].stop = inf;
	}
	int now = 0;
	do {
     
		now = move(now);
	} while (now != inf);
	for (int i = 1; i <= n; ++i) {
     
		if (a[i].stop == inf) {
     
			cout << "Infinity\n";
		} else {
     
			cout << a[i].stop << '\n';
		}
	}
	return 0;
}

你可能感兴趣的:(USACO题解)