USACO历年青铜组真题解析 | 2018年2月HoofBall

学习C++从娃娃抓起!记录下USACO(美国信息学奥赛)备考青铜组别比赛学习过程中的题目,记录每一个瞬间。

附上汇总贴:USACO历年青铜组真题解析 | 汇总-CSDN博客


【题目描述】

为了准备即将到来的蹄球锦标赛,Farmer John正在训练他的N头奶牛(方便起见,编号为1…N,其中1≤N≤100)进行传球。这些奶牛在牛棚一侧沿直线排列,第i号奶牛位于距离牛棚xi的地方(1≤xi≤1000)。每头奶牛都在不同的位置上。

在训练开始的时候,Farmer John会将若干个球传给不同的奶牛。当第i号奶牛接到球时,无论是从Farmer John或是从另一头奶牛传来的,她会将球传给最近的奶牛(如果有多头奶牛与她距离相同,她会传给其中距左边最远的那头奶牛)。为了使所有奶牛都有机会练习到传球,Farmer John想要确保每头奶牛都持球至少一次。帮助他求出为了达到这一目的他开始时至少要传出的球的数量。假设他在开始的时候能将球传给最适当的一组奶牛。

【输入】

输入的第一行包含N。第二行包含N个用空格分隔的整数,其中第i个整数为xi。

【输出】

输出Farmer John开始的时候最少需要传出的球的数量,使得所有奶牛至少持球一次。

【输入样例】

5
7 1 3 11 4

【输出样例】

2

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n, a[105], cnt[105], nxt[105], ans=0;
ifstream filein("hoofball.in");
ofstream fileout("hoofball.out");
int main()
{
    filein >> n;  // 输入n
    for (int i=1; i<=n; i++) {  // 依次输入n个数
        filein >> a[i];
    }
    sort(a+1, a+n+1);  // 对数进行排序
    nxt[1] = 2;  // 默认左端点放一个球
    cnt[2] = 1;  // 指向右边一个端点
    nxt[n] = n-1;  // 默认右端点放一个球
    cnt[n-1] = 1;  // 指向左边一个端点
    for (int i=2; i<n; i++) {  // 从第2个球开始遍历
        if (a[i]-a[i-1] > a[i+1]-a[i]) {  // 比较向左的距离和向右的距离,如果向右距离更短
            nxt[i] = i+1;  // 则向右移动
            cnt[i+1]++;  // 右边那个球的计数器自增1
        } else {  // 如果向左距离更短
            nxt[i] = i-1;  // 则向左移动
            cnt[i-1]++;  // 左边那个球的计数器自增1
        }
    }
    for (int i=1; i<=n; i++) {  // 先遍历一遍n个奶牛
        if (cnt[i]==0) ans++;  // 哪些计数为0的奶牛就是把球放这个位置后不再回头的位置(即可以放球的位置)
    }
    for (int i=1; i<n; i++) {  // 再遍历一遍n-1个奶牛(因为要判断i+1,所以i不能等于n)
        if (cnt[i]==1 && cnt[i+1]==1 && nxt[i]==i+1 && nxt[i+1]==i) ans++;  // 对于两个奶牛的nxt互相指向对方的,且cnt均为1(表示一上来就互相指向对方,而不是经历多轮遍历后才互相指向对方的),这样的一对奶牛需要单独再放一个球
    }
    fileout << ans << endl;  // 打印结果
    return 0;
}

【运行结果】

5
7 1 3 11 4
2

猜你喜欢

转载自blog.csdn.net/guolianggsta/article/details/134923397
今日推荐