【第五篇blog】第二次模拟赛反思与解析

模拟赛题目选自USACO铜组(T2,T3,T4)与银组(T1)

个人翻译,严禁转载

——————————————————————我是更新提示分割线———————————————————————

<第一次更新>使用完整题目,切勿转载。

—————————————————————我是华丽丽的正文分割线——————————————————————

本套题典型的难度打乱(虽然难度都不够hh),先从t2讲起。

T2

题目描述
猫为什么过马路是一个历史悠久的问题,并且得到了科学界极大的重视。 令人惊讶的是,关于犬过马路的研究文献却很少。 犬国军政大臣HSQ意识到了问题的重要,于是他与犬国大学合作研究这一问题。HSQ的工作就是记录犬穿过马路的次数,他认真的记录了关于犬的位置的数据,并在一天内进行了一系列观察。它记录了每只犬的编号和特在马路的哪一侧(编号是个整数且小于等于10,因为犬国只有10只犬) 根据农民约翰记录的数据,请帮助他计算确定的犬过马路的次数。如果连续看到一只犬出现在道路的两侧,就会确认过了一次马路
输入格式
第一行输入包含观察次数N,一个最多为100的正整数。
接下来N行每一行包含一个观察结果,由两个数构成,第一个数是犬编号,第二个数是0或1,表示位置(道路一侧为0,另一侧为1)。
输出格式
一个数据,输出过马路次数。。
样例数据
input
8
3 1
3 0
6 0
2 1
4 1
3 0
4 0
3 1
output
3
在这个例子中,犬3过马路两次 特首先出现在第1侧,然后出现在第0边,然后再出现在第1边。犬4过马路一次。犬2和6似乎没有过马路。
数据规模与约定
时间限制:1s
空间限制:256MB

题意:输入n组数据,每一组数据代表编号为i的狗所在的方位,检测到同一只狗在1,0两个方位,即视为该狗过了一次马路。输出所有狗过马路的总次数。
解析:对数据进行扫描,统计即可,类似于一些简单模拟题。
误区:统计算法不需要进行排序,进行排序很容易导致一些细节问题,直接统计可以避免不必要的细节处理。(已中招这里写图片描述
思路:输入一组数据,先将数据储存在两个临时变量中,写一个函数查找编号i的狗是否已经有过储存记录,如果有,判断两次出现的位置是否在道路两侧,如果是,sum++;
参考代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,sum=0;
struct doge//结构体“狗”:成员参数:编号(num),位置(road)
{
    int num,road;
}dog[105];
int searchr(int v,int g)//搜索函数:形参:狗的编号(v),所在位置(g)
{
    for(int k=1;k<=n;k++)//查找该狗是否有出现记录
    {
        if(dog[k].num==v&&dog[k].road!=g)//若该狗有出现记录且两次位置不同,返回该狗的编号
        {
            return k;
        }
    }
    return 0;//若不成立,返回0
} 
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int fnum,froad;//临时变量
        cin>>fnum>>froad;
        int result=searchr(fnum,froad);//result=查找函数的返回值
        if(result!=0)//result不等于0,说明已经查找到了
        {
            sum++;//答案增加
            dog[result].road=froad;//编号为result的狗的位置更新
            i--;//当前狗编号减1;
            n--;//因为检测到同一只狗,所以总数减1
            continue;//继续下一组数据
        }
        dog[i].num=fnum;//若不成立,储存一只新的狗
        dog[i].road=froad;
    }
    cout<<sum<<endl;//输出
    return 0;
}

T3

题目描述
男神Sharpland农场的布局相当奇特,他的牛白天吃草的田野周围,绕着一条大型圆形道路。
每天早晨,牛在前往田野时要穿过这条路,每天晚上,他们离开田野回到谷仓时,都会再过一遍这条路。
正如我们所知,牛是一种习惯性动物,它们每天都以同样的方式过马路。每头牛都在不同的点进入田野,走出田野,并且所有的点都与其他的不同。Sharpland拥有26头牛,他把他们命名为A到Z,所以在这条路上有52个点。Sharpland通过绕着圆形道路顺时针方向扫描这些点来记录它们,写下每一个点所属的牛的名字,最终形成一个有52个字符的字符串,字母表中的每一个字母都出现了两次。
他没有记录哪些点是进入田野的点,哪些是走出田野的点。
看着他的地图,Sharpland很好奇,在一天中会有多少对不同的奶牛穿过马路。如果牛A从入口到出口的路径必须穿过牛B从入口到出口的路径,他把这对奶牛(A,B)称为交叉对。请帮助Sharpland计算出交叉对的数量。
输入格式
输入由一行包含52个大写字母的字符串组成。其中每个大写字母都出现了两次。
输出格式
请输出交叉对的总数。
样例数据
input
ABCCABDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ
output
1(在这个样例中,只有牛A和牛B是一对交叉对。)
数据规模与约定
时间限制:1s1s
空间限制:256MB

题意:检测由26个字母*2=56个字符的字符串中交叉对的对数。
解析:对每一个字母的两次出现的位置进行标记,判断是否符合要求。
重点:判断是否为交叉对的三个判断条件一定要仔细琢磨推理。大小判断相反会导致结果全错(又中招这里写图片描述
思路:输入,一个函数对每个字母两次所在位置分别记录,两重循环枚举两个字母,判断是否符合交叉对的要求。
参考代码如下:

#include<bits/stdc++.h>
using namespace std;
char a[100];
int ans=0;
struct lett//结构体“字母”:成员:首次出现位置和第二次出现位置
{
    int first,last;
}letter[100];
void numer()//标号函数
{
    for(int i=0;i<=51;i++)
    {
        int num=a[i]-'A'+1;//求该字母是第几个字母,并在letter数组中标记
        if(letter[num].first!=0)
        {
            letter[num].last=i+1;
        }
        else 
        {
            letter[num].first=i+1;
        }
    } 
}
int main()
{
    cin>>a;
    numer(); 
    for(int i=1;i<=25;i++)
    {
        for(int j=i+1;j<=26;j++)
        {
            if(letter[i].first<letter[j].first&&letter[i].last<letter[j].last&&letter[j].first<letter[i].last)
//检测条件,字母i的第一次出现位置小于字母j的第一次出现位置;字母i的第二次出现位置小于字母j的第一次出现位置;字母j的第一次出现位置小于字母i的第二次出现位置
            {
                ans++;
            } 
        }
    }
    cout<<ans<<endl;
} 

T4

题目描述
Farmer John在他晚年的时候脾气变得越来越暴躁,因为他经常忘记自己的奶牛长什么样,所以他修了一个大栅栏,不让邻居的奶牛来参观。
Fj的奶牛们表示很难过,不仅仅是因为他们没法和朋友们一起愉快的玩耍,而且他们也没法参加他们期待已久的国际奥林匹克挤奶大赛了。
但还是有一些奶牛可以通过栅栏,到fj的农场,不过他们只能从一个小门一个一个进去,还要回答一系列神奇的问题,于是奶牛们经常要排很长的队伍才能成功进入。
对于每n只拜访这个农场的奶牛,你被告知她到达门口的时间以及她回答问题所需要的时间。
在任何时间只有一头奶牛可以被提问,所以如果同一时间有许多奶牛到达,她们可能要排队等待,逐一解决。
举个栗子,如果一只奶牛在时间为5的时候到达,并且回答问题用的时间为7,另一只奶牛在时间为8的时候到达,就需要等到时间为12时再开始回答问题。
请你确定所有奶牛都能进入农场的最早时间。
输入格式
第一行是正整数N(N<=100),
接下来的N行有两个正整数a,b,(a,b<=1,000,000),
a指的是奶牛到达小门的时间,b表示这个奶牛回答问题需要的时间
输出格式
输出一个数,表示所有奶牛都进入农场时的最早时间
样例数据
input
3
2 1
8 3
5 7
output
15
在这里,第一头奶牛在两点到达,并很快被处理。直到第三头牛在5点到达,并开始处理时,大门一直处于短暂的空闲状态。第二只母牛会在8点钟到达,到5 +7= 12时开始回答问题,12 +3 = 15时时结束。
数据规模与约定
时间限制:1s1s
空间限制:256MB

题意:求所有奶牛都完成的最短完成时间。
解析:这里需要用到结构体排序,按到达时间排序,然后模拟统计。
误区:排序关键字是到达时间,并非所用时间。若想在最短时间内处理完,需要让小门的空闲时间最少,就必须按到达时间排序。
思路:输入,排序,模拟,输出。
参考代码如下:

#include<bits/stdc++.h>
using namespace std;
struct m//结构体“牛”:成员:到达时间(to),所需时间(time)
{
    int to,time;
}mi[105];
bool cmp(m x,m y)//排序函数,关键字:到达时间
{
    return x.to<y.to;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>mi[i].to>>mi[i].time;
    }
    sort(mi+1,mi+n+1,cmp);
    int sum=mi[1].to;
    for(int i=1;i<=n;i++)
    {
        sum+=mi[i].time;//加上所需时间
        //cout<<sum<<endl;
        if(sum<mi[i+1].to)sum=mi[i+1].to;//若第i只牛结束后第i+1只牛还没到,时间等于第i+1只牛的到达时间
    }
    cout<<sum<<endl;
} 

T1

题目描述
农夫约翰发现,当他的奶牛在附近有另一头奶牛获得其他奶牛支持时候,他就更容易挤牛奶了。因此,他想把他的M头奶牛(M < 1000000000,M是偶数)分割为M/2对。然后,每一对将被引到谷仓里的一个单独的小隔间里挤奶。每一个隔间的挤牛奶将同时进行。
让事情变得有点复杂的是,每一个农夫约翰的奶牛都有不同的产奶量。如果奶牛产奶量是A和B,那么就需要用A+B的时间来给它们挤奶。
请帮助农场主约翰确定整个挤奶过程所需的最短时间。
输入格式
第一行为N(N<100000)接下来的N行每一行都有两个整数x,y,表示有x头奶牛的产奶量为y(1≤y≤1,000,000,000)。x的和是整数M。
输出格式
输出整个过程的最短时间。
样例数据
input
3
1 8
2 5
1 2
output
10
样例说明:这里 4头奶牛的产奶量为2,5,5,8。显然,将他们分为2+8 和5+5所需的时间最短(其他任意分配都会导致有一组奶牛的时间超过10),所需时间为10
数据规模与约定
时间限制:1s1s
空间限制:256MB
题意:计算在怎样分配m/2对奶牛的情况下所需时间最少。
解析:以奶牛所需时间为关键字进行排序,最大和最小分配,就不会超出最短极限。
重点:奶牛数据中,还有另外一个关键字,所需该时间的奶牛的数量。排序完成后对该数据就得进行特殊处理。
思路:以牛的所需时间排序,对时间长的牛和时间短的牛左右逼近匹配,求最大值。
参考代码如下:

#include<bits/stdc++.h>
using namespace std;
struct m//结构体“牛”:成员:数量,时间
{
    int num,time;
}mi[100005];
bool cmp(m p1,m p2)//以时间为关键字排序
{
    return p1.time>p2.time;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>mi[i].num>>mi[i].time;
    }
    sort(mi+1,mi+n+1,cmp);
    int max=-1,left=1,right=n;
    while(left<right)//左右逼近,大小匹配
    {
        if((mi[left].time+mi[right].time)>max)max=mi[left].time+mi[right].time;//大于最大值便更新
        if(mi[left].num==1)left++;//判断该种牛是否有多只,若有,减数量,若没,改位置。下同
        else mi[left].num--;
        if(mi[right].num==1)right--;
        else mi[right].num--;
    }
    cout<<max<<endl;
} 

总结

通览题目,按难度排序,合理安排考试时间,随时存盘代码,谨防IDE奔溃。
—————————————————————我是华丽丽的正文分割线——————————————————————

——————————————————————我是讲废话的分割线———————————————————————

猜你喜欢

转载自blog.csdn.net/prasnip_/article/details/78700047
今日推荐