USACO 2020 December Contest, Bronze (铜组测试一)解题报告

本文介绍了USACO2020年12月比赛铜组的三道题目,包括T1ABC问题、T2雏菊花环和T3一成不变。对于每道题目,提供了问题描述、输入输出格式、解题思路和示例代码,主要涉及排序、数学计算和动态规划等算法。
摘要由CSDN通过智能技术生成

USACO 2020 December Contest, Bronze (铜组测试一)解题报告

--------------cadifobp0802

T1 ABC问题

问题描述

Farmer John 的奶牛正在 “mooZ” 视频会议平台上举行每日集会。她们发明了一个简单的数字游戏,为会议增添一些乐趣。

Elsie 有三个正整数 A、B 和 C(A <= B <= C)。这些数字是保密的,她不会直接透露给她的姐妹 Bessie。她告诉 Bessie 七个范围在 1 … 10^9 之间的整数(不一定各不相同),并宣称这是 A、B、C、A+B、B+C、C+A 和 A+B+C 的某种排列。

给定这七个整数,请帮助 Bessie 求出 A、B 和 C。可以证明,答案是唯一的。

输入格式

输入一行,包含七个空格分隔的整数。

输出格式

输出 A、B 和 C,用空格分隔。

输入样例

2 2 11 4 9 7 9

输出样例

2 2 7

测试点性质

测试点 2-3 满足 C <= 50。
测试点 4-10 没有额外限制。

我的想法

这道题首先进行排序,由于A<=B<=C,所以最小的两个一定是A和B,最大的一定是A+B+C,进而求出C。
代码如下:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 10

int l[MAXN], a, b, c;

int main(){
	//freopen("abc.in", "r", stdin);
	//freopen("abc.out", "w", stdout);
	for (int i = 1; i <= 7; ++i)
		scanf("%d", &l[i]);
	sort(l + 1, l + 7 + 1);
	a = l[1];
	b = l[2];
	c = l[7] - a - b;
	printf("%d %d %d\n", a, b, c);
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}

T2 雏菊花环

问题描述

每天,作为她绕农场行走的一部分,奶牛 Bessie 会经过她最喜爱的草地,其中种有 N 朵花(五颜六色的雏菊),编号为 1…N(1≤N≤100),排列成一行。花 i 有 pi 朵花瓣(1≤pi≤1000)。
作为一名崭露头角的摄影家,Bessie 决定给这些花拍些照片。具体地说,对于每一对满足 1≤i≤j≤N 的花 (i,j),Bessie 会给从花 i 到花 j 之间的所有花(包括 i 和 j)拍一张照。

后来 Bessie 查看这些照片时注意到有些照片里存在「平均」的花——一朵恰好有 P 朵花瓣的花,其中 P 等于照片中所有花的花瓣数量的平均值。

Bessie 的照片中有几张存在平均的花?

输入格式

输入的第一行包含 N。第二行包含 N 个空格分隔的整数 p1…pN。

输出格式

输出存在平均的花的照片数量。

输入样例

4
1 1 2 3

输出样例

6

样例说明

每张仅包含一朵花的照片均会被计入答案(在这个样例中有 4 张)。另外,在这个样例中 (i,j) 为 (1,2) 和 (2,4) 所对应的照片也存在平均的花。

我的想法

由于数据范围很小,所以我们可以用O(2n^3)的代码直接暴力通过。枚举每一个区间,计算平均数,然后查找,很快就解决了。
代码如下:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 110

int n, p[MAXN], ans = 0, cnt = 0;

int main(){
	//freopen("daisy.in", "r", stdin);
	//freopen("daisy.out", "w", stdout);
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i)
		scanf("%d", &p[i]);
	ans = n;
	for (int i = 1; i < n; ++i)
		for (int j = i + 1; j <= n; ++j) {
			cnt = 0;
			for (int k = i; k <= j; ++k)
				cnt += p[k];//枚举区间累加
			bool flag = false;
			for (int k = i; k <= j; ++k)
				if (p[k] * (j - i + 1) == cnt){
					flag = true;
					break;
				}//查找
			if (flag)
				ans++;
		}
	printf("%d\n", ans);
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}

T3 一成不变

问题描述

Farmer John 最近扩大了他的农场,从奶牛们的角度看来这个农场相当于是无限大了!奶牛们将农场上放牧的区域想作是一个由正方形方格组成的无限大二维方阵,每个方格中均有美味的草(将每个方格看作是棋盘上的一个方格)。Farmer John 的 N 头奶牛(1≤N≤50)初始时位于不同的方格中,一部分朝向北面,一部分朝向东面。

每一小时,每头奶牛会执行以下二者之一:

如果她当前所在的方格里的草已经被其他奶牛吃掉了,则她会停下。
吃完她当前所在的方格中的所有草,并向她朝向的方向移动一个方格。
经过一段时间,每头奶牛的身后会留下一条被啃秃了的轨迹。

如果两头奶牛在一次移动中移动到了同一个有草的方格,她们会分享这个方格中的草,并在下一个小时继续沿她们朝向的方向移动。

请求出每头奶牛吃到的草的数量。有些奶牛永远不会停下,从而吃到无限多的草。

输入格式

输入的第一行包含 N。以下 N 行,每行描述一头奶牛的起始位置,包含一个字符 N(表示朝向北面) 或 E(表示朝向东面),以及两个非负整数 x 和 y(,)表示方格的坐标。所有 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
5

测试点性质

测试点 2-5 中,所有坐标不超过 100。
测试点 6-10 没有额外限制。

我的想法

我们可以先枚举每两头牛之间的关系,如果这两头牛的路线交叉且不是同时到达交叉点,那么就有可能发生一次阻碍,记录起来。最后一起综合来求每头牛吃的草的数量。
由于可能会出现一头牛本来可能会阻碍另一头牛,但是在到达阻碍点之前就被其它的牛阻碍了去路,那么它就不能成功阻挡住另一头牛前进。我们可以按照时间顺序来依次向后判断,如果出现这种情况直接跳过。
代码如下:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 60

struct nod{
	int x, y;//坐标
	char dic;//方向
	int tal = INT_MAX;//吃的草的数量
}cw[MAXN];

struct nodd{
	int i, j, v, u;
	//表示如果不考虑其它奶牛,第i头奶牛会被第j头奶牛挡住去路,阻碍点离奶牛i距离为v,离奶牛j距离为u
}vis[MAXN * MAXN];

int n, k = 0;

bool cmp (nodd p, nodd q) {
	return p.v < q.v || (p.v == q.v && p.u < q.u);
}//排序

int main(){
	//freopen("stuct.in", "r", stdin);
	//freopen("stuct.out", "w", stdout);
	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> cw[i].dic >> cw[i].x >> cw[i].y;
	for (int i = 1; i < n; ++i) {
		char now = cw[i].dic;
		for (int j = i + 1; j <= n; ++j) {
			if (now != cw[j].dic) {//只有不同方向的奶牛路线才会产生交叉
				if (now == 'E') {
					if (cw[i].x <= cw[j].x && cw[i].y >= cw[j].y) {//排除不交叉的情况
						int r = cw[j].x - cw[i].x, u = cw[i].y - cw[j].y;//算出到阻碍点的距离
						if (r > u) {
							vis[++k].v = r;
							vis[k].i = i;
							vis[k].j = j;
							vis[k].u = u;
						}
						else if (u > r) {
							vis[++k].v = u;
							vis[k].i = j;
							vis[k].j = i;
							vis[k].u = r;
						}//记录到vis数组里
					}
				}
				else {
					if (cw[i].x >= cw[j].x && cw[i].y <= cw[j].y) {
						int r = cw[i].x - cw[j].x, u = cw[j].y - cw[i].y;
						if (r > u) {
							vis[++k].v = r;
							vis[k].i = j;
							vis[k].j = i;
							vis[k].u = u;
						}
						else if (u > r) {
							vis[++k].v = u;
							vis[k].i = i;
							vis[k].j = j;
							vis[k].u = r;
						}
					}
				}//分两种情况讨论
			}
		}
	}
	sort(vis + 1, vis + k + 1, cmp);//按被阻碍点被阻碍的时间进行排序,从前往后去分析该点是否会被阻碍
	for (int i = 1; i <= k; ++i) {
		if (cw[vis[i].j].tal < vis[i].u)
			continue;//如果阻碍的奶牛在到达阻碍点之前就停止前进,则不能成功阻碍
		else
			cw[vis[i].i].tal = min (cw[vis[i].i].tal, vis[i].v);//否则进行更改
	}
	for (int i = 1; i <= n; ++i)
		if (cw[i].tal == INT_MAX)
			printf("Infinity\n");
		else
			printf("%d\n", cw[i].tal);
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值